混淆与Enum#detect`nil`输出

时间:2013-03-29 18:32:44

标签: ruby

enum#detect说:

  

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

现在我正在尝试以下内容:

nil.call
#NoMethodError: undefined method `call' for nil:NilClass
#       from (irb):13
#       from C:/Ruby200/bin/irb:12:in `<main>'


(1..10).detect(x = 2) { |i| i % 5 == 0 and i % 7 == 0 }
#NoMethodError: undefined method `call' for 2:Fixnum
#       from (irb):15:in `detect'
#       from (irb):15
        from C:/Ruby200/bin/irb:12:in `<main>'

现在我的问题是为什么下面没有出现同样的错误:

(1..10).detect(x = nil) { |i| i % 5 == 0 and i % 7 == 0 }
#=> nil
(1..10).detect(x = nil) { |i| p x; i % 5 == 0 and i % 7 == 0 }
#nil
#nil
#nil
#nil
#nil
#nil
#nil
#nil
#nil
#nil
#=> nil

2 个答案:

答案 0 :(得分:1)

如果查看detect方法的源代码(单击文档页面上的“查看源代码”),您会看到如果参数为<,它只会尝试执行call strong>不 nil

if (!NIL_P(if_none)) {
  return rb_funcall(if_none, id_call, 0, 0);
}

答案 1 :(得分:0)

  

如果没有对象匹配,则调用ifnone并在指定时返回其结果,否则返回nil。

我认为您正在以不同于预期的方式解析该句子。这里的意思是:

if no object matches
  if ifnone is set
    return ifnone.call
  else
    return nil
  end
end

如果传入nil作为参数,则表示ifnone未设置,因此不会调用它。只有在为nil传递{{1}}以外的值时才会调用它。