Project

General

Profile

Actions

Feature #13795

open

Hash#select return type does not match Hash#find_all

Added by davidarnold (David Arnold) almost 5 years ago. Updated about 3 years ago.

Status:
Open
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:82312]

Description

Enumerable#select and Enumerable#find_all are aliases. Hash is_a Enumerable, yet only Hash#select was overridden to return a Hash, with Hash#find_all still returning an Array. This is confusing since the message is that you can use select and find_all interchangeably for Enumerable, yet when you get to Hash, there are warnings that it is no longer true.

Also any code that expects to call select on an Enumerable and get an array back (as documented) could break, but only for Hash#select.

Example:

def select_many(*enumerables, &block)
  result = []
  enumerables.each do |e|
    result.concat e.select(&block)
  end
  result
end

select_many([1, 2], [3, 4]) { |x| x % 2 == 0 } #=> [2, 4]

select_many({ 1 => 2 }, { 3 => 4 }) { |k, v| k < 2 } #=> TypeError: no implicit conversion of Hash into Array

Should Hash#find_all also return a Hash for consistency? Or, given the fact that calling #to_h on the resulting Array is so easy, should Hash#select revert to the Enumerable behavior of returning an Array?

Proposal 1:

h = { "a" => 100, "b" => 200, "c" => 300 }
h.find_all {|k,v| k > "a"}  #=> {"b" => 200, "c" => 300}

Proposal 2:

h = { "a" => 100, "b" => 200, "c" => 300 }
h.select {|k,v| k > "a"} #=> [["b", 200], ["c", 300]]
h.select {|k,v| k > "a"}.to_h #=> {"b" => 200, "c" => 300}
Actions

Also available in: Atom PDF