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/
prev 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).