Techioz Blog

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 つの要素の配列を生成するのはそのためです。