ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
From: matz@ruby.or.jp
To: ruby-core@ruby-lang.org
Subject: [ruby-core:96894] [Ruby master Feature#16435] Array#to_proc
Date: Thu, 16 Jan 2020 06:58:27 +0000 (UTC)	[thread overview]
Message-ID: <redmine.journal-83908.20200116065827.de1f35d57ca45990@ruby-lang.org> (raw)
In-Reply-To: redmine.issue-16435.20191219160138@ruby-lang.org

Issue #16435 has been updated by matz (Yukihiro Matsumoto).

Status changed from Open to Rejected

Rejected. `Array#to_proc` to too generic for queries. It only makes the code more cryptic.

Matz.


----------------------------------------
Feature #16435: Array#to_proc
https://bugs.ruby-lang.org/issues/16435#change-83908

* Author: zverok (Victor Shepelev)
* Status: Rejected
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
The idea is obvious, but I couldn't find it discussed anywhere on tracker before. Please point me at the previous discussions if any.

```ruby
class Array
  def to_proc
    proc { |v| v.dig(*self) }
  end
end
# Or, alternatively, see about alternatives at the end of proposal:
class Array
  def to_proc
    proc { |v| v[*self] }
  end
end

```
The implementation seems to provide clean and unambiguous collections indexing in Enumerators:
```ruby
# Basic objects data, which could be obtained from JSON, CSV, Database...
data = [
  {name: 'John', department: {id: 1, title: 'Engineering'}, salary: 1000}, 
  {name: 'Jane', department: {id: 1, title: 'Engineering'}, salary: 1200},
  {name: 'Boris', department: {id: 2, title: 'Accounting'}, salary: 800},
  {name: 'Alice', department: {id: 3, title: 'Management'}, salary: 1500}
]
data.map(&[:name])
# => ["John", "Jane", "Boris", "Alice"] 
data.min_by(&[:salary])
# => {:name=>"Boris", :department=>{:id=>2, :title=>"Accounting"}, :salary=>800} 
pp data.group_by(&[:department, :title])
# {"Engineering"=>
#   [{:name=>"John",
#     :department=>{:id=>1, :title=>"Engineering"},
#     :salary=>1000},
#    {:name=>"Jane",
#     :department=>{:id=>1, :title=>"Engineering"},
#     :salary=>1200}],
#  "Accounting"=>
#   [{:name=>"Boris",
#     :department=>{:id=>2, :title=>"Accounting"},
#     :salary=>800}],
#  "Management"=>
#   [{:name=>"Alice",
#     :department=>{:id=>3, :title=>"Management"},
#     :salary=>1500}]}

# Works with arrays, too:
data.map(&:values).map(&[0])
# => ["John", "Jane", "Boris", "Alice"]

# And with mixes:
data.group_by(&[:department, :title]).values.map(&[0, :name]) 
# => ["John", "Boris", "Alice"]
```

Naked structured data seems to be a common enough thing to make working with them easier.

Some prior info:

* Googling it around, I found the idea was first invented [back in 2014](https://thepugautomatic.com/2014/11/array-to-proc-for-hash-access/), and another one [in 2015](https://gist.github.com/geowy/39fde25ec2966f90a54b), not sure if it was proposed on the tracker.
* Other proposals for `Array#to_proc` was: to call several methods in sequence [1](http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/199820), [2](https://rails.lighthouseapp.com/projects/8994/tickets/1253-arrayto_proc), and to call method with argument [1](https://www.sanityinc.com/articles/adding-array-to-proc-to-ruby/), [2](https://bugs.ruby-lang.org/issues/10829), [3](https://www.rubydoc.info/github/estum/console_utils/Array:to_proc), to call several methods in parallel: [1](https://gist.github.com/shell/1120249)

Honestly, I feel that proposed usage is the most frequently needed.

Also, the readability of the version seems more or less straightforward:

```ruby
# Existing shortcut, for example:
data.map(&:keys)
# Is equivalent to
data.map { |x| x.keys }
#          ^^^^^ -- "just remove this part"

# Proposed shortcut:
data.map(&[:name])
# Is equivalent to
data.map { |x| x[:name] }
#          ^^^^^ -- "just remove this part"
```

**`dig` or `[]` alternative implementations**

It is up to discussion (if the whole idea holds water) whether `dig` should be used or just `[]`. The `dig` version is convenient for nested structures but slightly breaks "equivalency" shown above, and just `[]` version will allow this:
```ruby
data.map(&:values).map(&[1..-1])
# => [[{:id=>1, :title=>"Engineering"}, 1000], [{:id=>1, :title=>"Engineering"}, 1200], [{:id=>2, :title=>"Accounting"}, 800], [{:id=>3, :title=>"Management"}, 1500]]
```

Maybe, for the sake of explainability, "just `[]`" should be preferred, with digging performed by other means.



-- 
https://bugs.ruby-lang.org/

      parent reply	other threads:[~2020-01-16  6:58 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <redmine.issue-16435.20191219160138@ruby-lang.org>
2019-12-19 16:01 ` [ruby-core:96338] [Ruby master Feature#16435] Array#to_proc zverok.offline
2019-12-26 22:10 ` [ruby-core:96503] " daniel
2019-12-28 14:02 ` [ruby-core:96552] " zverok.offline
2019-12-30  2:40 ` [ruby-core:96588] " daniel
2019-12-30 14:41 ` [ruby-core:96593] " zverok.offline
2019-12-30 17:33 ` [ruby-core:96598] " daniel
2020-01-16  6:58 ` matz [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.ruby-lang.org/en/community/mailing-lists/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=redmine.journal-83908.20200116065827.de1f35d57ca45990@ruby-lang.org \
    --to=ruby-core@ruby-lang.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).