Project

General

Profile

Actions

Feature #21615

open

Introduce `Array#values`

Added by matheusrich (Matheus Richard) 2 days ago. Updated 1 day ago.

Status:
Open
Assignee:
-
Target version:
-
[ruby-core:123319]

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 and Hash already implement #values_at.
  • Hash implements #values but Array 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 to to_a, but I found it too broad of a change.
  • Array#each_value: redundant as Array#each already covers iteration.

Patch: https://github.com/ruby/ruby/pull/14641

Updated by nobu (Nobuyoshi Nakada) 2 days ago

matheusrich (Matheus Richard) wrote:

Add Array#values, returning self. Implementation could simply alias to itself:

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.

Actions #4

Updated by matheusrich (Matheus Richard) 2 days ago

  • Description updated (diff)

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.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0