【问题标题】:Why can't I pass a block variable to inject?为什么我不能传递一个块变量来注入?
【发布时间】:2014-07-11 10:42:05
【问题描述】:

给定,

  def wrapper &block
    (1..5).inject yield
  end

  proc = Proc.new {|sum, n| sum + n }

为什么我不能打这个电话?

  wrapper &proc
  => NoMethodError: undefined method `+' for nil:NilClass

当查看内部时,我看到注入无法分配备忘录或 obj,因为将 proc 重写为 proc = Proc.new {|memo, obj| puts memo ; puts obj } 返回 10 次迭代,什么都没有。我还注意到(1..5).inject 只接受一个参数,它作为初始备忘录传入的内容,从技术上讲,它不会将块作为真正的参数。

【问题讨论】:

标签: ruby


【解决方案1】:

这样做的方法是

def wrapper &block
  ( 1..5 ).reduce &block
end

p = proc { |a, b| a + b }

wrapper &p
#=> 15

但在您的问题中,您有趣地尝试使用yield。当你使用yield 时,你不需要显式提及&block 参数——一个方法不能拒绝一个块,它总是可以被方法内部的yield 调用。但是,yield 需要参数。使用yield实现目标的方法是:

def wrapper_2
  ( 1..5 ).reduce { |accumulator, input| yield accumulator, input }
end

这个提法还是有点尴尬。事实证明,即使不指定 &block 参数,也有一个秘密的方法可以在方法内部获取块,那就是在方法内部使用朴素的Proc.new

def wrapper_3
  ( 1..5 ).reduce &Proc.new
end

【讨论】:

    【解决方案2】:

    感谢您指出相关问题!我的谷歌搜索和网站搜索机制之前并没有将我指向那里。它帮助我看到我之前刚刚犯了一个愚蠢的语法错误(我尝试了(1..5).inject([]) proc 的调用),这让我误解了我所看到的。所以我实际上需要的是:

    def wrapper proc
      (1..5).inject 0, proc
    end
    

    【讨论】:

    • 你测试了吗?当我按照您在问题中指定的方式调用 wrapper &proc 来尝试您的 wrapper 时,它给了我一个错误。
    • 所以我也将调用更改为只是 wrapper proc,效果很好。我来到的下一步也让我感到难过:summer = Proc.new {|sum, n| sum + n}; rap = Proc.new {|proc| (1..5).inject 0, proc} ; curried = rap.curry ; curried[summer] 导致:TypeError: #<Proc:0x00000103132cd0@(pry):1> is not a symbol。 :c
    • 又一个愚蠢的错误!我需要这个:rap = Proc.new {|proc| (1..5).inject 0, &proc} 现在,瞧,它可以工作了。
    • 嗯,在定义 Proc 时,你可以只说 proc { |a, b| a + b } 而不是 Proc.new { |a, b| a + b }
    猜你喜欢
    • 1970-01-01
    • 2019-03-04
    • 1970-01-01
    • 1970-01-01
    • 2021-08-10
    • 1970-01-01
    • 2011-02-05
    • 2011-05-16
    • 2020-08-24
    相关资源
    最近更新 更多