为什么Enumerable#find /#detect即使在Hash上调用也会返回一个数组?

ste*_*ang 9 ruby arrays hash enumerable

/文档Enumerable#find#detect说:

find(ifnone = nil) { |obj| block } ? obj or nil
find(ifnone = nil) ? an_enumerator

传递枚举中的每个条目以阻止.返回第一个块不为false的块.如果没有对象匹配,则调用ifnone并在指定时返回其结果,否则返回nil.

但是,当在Hash上调用它时,结果将类型更改为Array而不是原始Hash.

是关于此数据类型的一些实现错误还是一些历史约定?

{a: 'a', b:'b'}.find {|k, v| v == 'b'}
# => [:b, 'b']
Run Code Online (Sandbox Code Playgroud)

ste*_*ang 5

Hash#detect选自遗传Enumerable#detect方法.

Enumerable模块产生多个方法(如sort,min,max包括detect等)的基础上each,它包括的类的方法Enumerable.

它并不关心如何each实现它

"......产生了集合的连续成员."来自ruby-doc

所以对于这个Hash#detect方法,它依赖于Hash#each行为,即:

对hsh中的每个键调用一次,将键值对作为参数传递.如果没有给出块,则返回枚举器.

h = { "a" => 100, "b" => 200 }
h.each {|key, value| puts "#{key} is #{value}" }
Run Code Online (Sandbox Code Playgroud)

因为Hash#each将哈希产生为两对数组,所以从Enumerable模块继承的所有方法都基于此工作.

这就是为什么Hash#detect生成一个两元素数组而不是一个哈希对象本身.