Enumerable#find/#detect がハッシュで呼び出された場合でも配列を返すのはなぜですか?
概要
Enumerable#find/#detect のドキュメントには次のように書かれています。
ただし、ハッシュで呼び出すと、結果の型が元のハッシュではなく配列に変更されます。
それは実装上の欠陥でしょうか、それともこのデータ型に関する歴史的な慣習でしょうか?
{a: 'a', b:'b'}.find {|k, v| v == 'b'}
# => [:b, 'b']
解決策
Hash#detect は Enumerable#detect メソッドから継承されます。
EnumerableモジュールはEnumerableを含むクラスの各メソッドを元に複数のメソッド(sort、min、max、detectなど)を生成します。
それぞれがどのように実装されているかは気にしません。
したがって、Hash#detect メソッドの場合、次のような Hash#each の動作に依存します。
h = { "a" => 100, "b" => 200 }
h.each {|key, value| puts "#{key} is #{value}" }
Hash#each は 2 つのペアの配列としてハッシュを生成するため、Enumerable モジュールから継承されたすべてのメソッドはこれに基づいて機能します。
Hash#detect がハッシュ オブジェクト自体ではなく 2 つの要素の配列を生成するのはそのためです。