.all的奇怪行为? {block}

时间:2015-05-10 18:18:53

标签: ruby

我今天正在调试一些代码,当时我意识到Enumerable#all?的表现并不像我想象的那样。

我使用此方法确定何时立即返回值。它看起来像这样:

def some_method(hash)
  unless hash.all? { |k, v| v.is_a? Float }
    return hash
  end

  # some other business logic
end

但有时候这个方法会被发送一个空哈希,all?的结果不是我所期望的。

以下是一些正常情景:

[7] pry(main)> {'count' => 1}.all? { |k, v| v.is_a? Float }
=> false
[8] pry(main)> {'count' => 2.5 }.all? { |k, v| v.is_a? Float }
=> true

这是奇怪的地方:

[6] pry(main)> {}.all? { |k, v| v.is_a? Float }
=> true

我不希望这会返回true,事实上我希望得到一个"No method .is_a? for NilClass",但我会回来。有谁知道这是为什么?

Ruby 2.2.0

3 个答案:

答案 0 :(得分:1)

由于块永远不会被执行,因此无法抛出$sql = "INSERT INTO MyGuests (firstname, lastname, email) VALUES ('John', 'Doe', 'john@example.com')"; 错误(除了No method .is_a? for NilClass已在Object上实现,.is_a?显然来自{ {1}}。)

有人可能希望NilClass在空枚举器上返回Object,但这就像是设计问题。

您可以单击文档中的all?并确保方法“假设结果为true,并在第一个块返回false时将其设置为false”。此方法实现。

答案 1 :(得分:1)

文档的关键部分是"如果块永远不会返回false或nil,则该方法返回true。"

使用{}.all? { |k, v| v.is_a? Float }块永远不会被执行(因为地图是空的)。因此,块永远不会返回false或nil,因此该方法返回true。

答案 2 :(得分:1)

当您查看documentation for the all? method, as defined in the Enumeration Module in Ruby 2.2

时,这背后的原因非常简单
  

如果块永远不返回false或nil

,则该方法返回true

all?方法为可枚举的每个元素执行块。因为空哈希不包含任何迭代,所以块永远不会被执行。因此,该方法返回true