【问题标题】:Confusion with Enum#detect `nil` output与 Enum#detect `nil` 输出混淆
【发布时间】:2013-03-29 18:32:44
【问题描述】:

enum#detect 说:

将枚举中的每个条目传递给阻塞。返回第一个不为假的块。如果没有对象匹配,则调用 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

【问题讨论】:

    标签: ruby


    【解决方案1】:

    如果您查看 detect 方法的源代码(单击文档页面上的“查看源代码”),您会发现它仅在参数为 notcall /strong>nil:

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

    【讨论】:

    【解决方案2】:

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

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

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

    如果你传入nil 作为参数,那算作ifnone 没有被设置,所以它不会被调用。仅当您为其传递 nil 以外的值时才会调用它。

    【讨论】:

    • 我设置了x = nil,那怎么办?如果您看到最后一个代码输出,则所有nil 输出都作为输出。这意味着x 设置为nil
    • @iAmRubuuu 是的,x 设置为 nil,因为您设置为 nil。我真的不明白你的问题。请注意foo(x=bar)x=bar; foo(x) 相同。
    • 嗯我从另一个答案中得到了答案。我的意思是说不支持nil.call,但是为什么最后一个代码成功了?
    • @iAmRubuuu 最后一段代码是通过什么方式成功的?它打印 nil 很多,因为您将 p x 放在块中,而 xnil。在这两种情况下,都没有调用 ifnone 函数。仅当您将非零参数传递给 detect 时才会发生这种情况。
    • 你没有明白我的意思。你说-if ifnone is set return ifnone.call。在我的情况下,ifnonex,它设置为nil。所以根据你nil.call 应该执行。但这不是事实,实际上它在non nil 值上调用call。就是这样。
    猜你喜欢
    • 2013-03-05
    • 1970-01-01
    • 2020-11-17
    • 2014-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多