【问题标题】:Is there any difference in using `yield self` in a method with parameter `&block` and `yield self` in a method without a parameter `&block`?在带有参数“&block”的方法中使用“yield self”和在没有参数“&block”的方法中使用“yield self”有什么区别吗?
【发布时间】:2017-09-09 12:16:45
【问题描述】:

我明白了

def a(&block)
  block.call(self)
end

def a()
  yield self
end

如果我假设有这样一个块a {},会导致相同的结果。我的问题是 - 因为我偶然发现了一些类似的代码,它是否有任何区别或者是否有任何优势(如果我不使用变量/引用块):

def a(&block)
  yield self
end

这是一个具体的案例,我不明白&block的用法:

def rule(code, name, &block)
  @rules = [] if @rules.nil?
  @rules << Rule.new(code, name)
  yield self
end

【问题讨论】:

  • Block Argument 的文档显示了不同的用例。
  • @Stefan 我添加了一个我不明白 &block 用法的具体案例,也许我错过了一些东西,所以你可以看看吗?除此之外,我还阅读了文档,它符合我的理解。
  • 如果您不打算明确使用它,请不要将其添加到列表中。它使调用变慢并且令人困惑。
  • @ndn “这很令人困惑” - 特别是对于初学者。我认为这导致了这个问题。 ;)

标签: ruby yield


【解决方案1】:

两者的主要区别

def pass_block
  yield
end
pass_block { 'hi' } #=> 'hi'

def pass_proc(&blk)
  blk.call
end
pass_proc  { 'hi' } #=> 'hi'

也就是说,blkProc 的一个实例,是一个对象,因此可以传递给其他方法。相比之下,块不是对象,因此不能被传递。

def pass_proc(&blk)
  puts "blk.is_a?(Proc)=#{blk.is_a?(Proc)}"
  receive_proc(blk)
end

def receive_proc(proc)
  proc.call
end

pass_proc { 'ho' }
blk.is_a?(Proc)=true
  #=> "ho" 

【讨论】:

    【解决方案2】:

    我能想到的唯一好处是自省:

    def foo;       end
    def bar(&blk); end
    
    method(:foo).parameters  #=> []
    method(:bar).parameters  #=> [[:block, :blk]]
    

    IDE 和文档生成器可以利用这一点。但是,它不影响 Ruby 的参数传递。调用方法时,无论是声明还是调用,都可以传递或省略块。

    【讨论】:

    • 至少对我来说,不仅仅是内省。我发现查看方法签名并查看最后一个参数是否有前导 &amp; 与查看整个方法并尝试在某处找到 yield 相比要容易得多。
    猜你喜欢
    • 2020-06-16
    • 1970-01-01
    • 1970-01-01
    • 2016-12-01
    • 1970-01-01
    • 2014-06-06
    • 2016-02-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多