Feature #21615
openIntroduce `Array#values`
Description
Motivation¶
In Ruby code, it's common to accept arrays and hashes and treat them uniformly as collections of values. Hash
exposes #values
, but Array
does not, which pushes developers toward is_a?
/respond_to?
branching.
Following the Principle of Least Surprise, users may reasonably expect Array#values
to exist because:
- Both
Array
andHash
already implement#values_at
. -
Hash
implements#values
butArray
does not.
Example¶
Today:
def normalize_records(input)
items = input.respond_to?(:values) ? input.values : input
items.each do |item|
do_stuff_with_item(item)
end
end
With Array#values
:
def normalize_records(input)
input.values.each do |item|
do_stuff_with_item(item)
end
end
Proposal¶
Add Array#values
, returning a copy of the elements of self
.
This yields a uniform interface for Array
and Hash
values without type checks.
Alternatives considered¶
-
Enumerable#values
: defaulting toto_a
, but I found it too broad of a change. -
Array#each_value
: redundant asArray#each
already covers iteration.
Updated by nobu (Nobuyoshi Nakada) 2 days ago
matheusrich (Matheus Richard) wrote:
Add
Array#values
, returningself
. Implementation could simply alias toitself
:
I think it should be Array.new(*self)
.
Hash#values
returns a new Array
, non-frozen and independent from the receiver.
Updated by nobu (Nobuyoshi Nakada) 2 days ago
ยท Edited
matheusrich (Matheus Richard) wrote:
Following the Principle of Least Surprise, users may reasonably expect
Array#values
to exist because:
"PoLS" is a word not to say at a proposal.
That word is negative to convince us.
We are not sure who started to say the word, but Ruby itself hasn't advertised it.
With
Array#values
:def normalize_records(input) input.values.each do |item| do_stuff_with_item(item) end end
Why not to introduce Array#each_value
?
Updated by matheusrich (Matheus Richard) 2 days ago
I think it should be Array.new(*self).
I can do that, sure.
That word is negative to convince us.
Noted! Good to know.
Why not to introduce Array#each_value?
I think it feels clunkier than array.values.each
, but is an alternative I considered. IMO it still makes me expect that a #values
method would exist since it would be a word present in values_at
, fetch_values
and each_value
.
IMO both could be added, so Array has an interface even more similar to Hash, but I decided to keep this small.
Updated by Dan0042 (Daniel DeLorme) 1 day ago
I understand the idea of making core collection classes ducktype-compatible, but in that case this proposal should also include Set#values
Updated by matheusrich (Matheus Richard) 1 day ago
@Dan0042 I considered that. I thought it would be too much for one PR. I'll wait for more feedback, and if people are positive about this, I'll propose Set#values
too.