Ruby:如何正确使用`yield`将未命名的代码块传递给Integer#times方法?

时间:2018-04-03 22:36:47

标签: ruby

我正在学习Ruby,并且由于没有特殊原因,我想将yield对象传递给Integer #times方法,以便多次调用yield代码块。以下是我使用命名代码块的方法:

def withNamedCodeBlock &b
  3.times(&b)
end
withNamedCodeBlock {print "Go "}
#returns Go Go Go

现在,我想做同样的事情,但没有命名的代码块;我希望使用yield关键字来实现这一目标。这是我尝试和失败的方式:

def withYield
  3.times(&yield)
end
withYield {print "Go "}
#returns Go => #<Enumerator: 3:times>
#I expect it to return Go Go Go 

我仍然围绕着将代码块传递给方法的各种方法,所以有关此方面的其他信息表示赞赏。

3 个答案:

答案 0 :(得分:4)

  

我想将yield对象传递给Integer#times方法,以便多次调用yield代码块

yield不是一个对象,也不是一个块。它甚至不是方法调用。它是产生控制传递块的关键字。如果你想对块做任何其他事情(保存以供日后使用,等等),你必须给它命名。

答案 1 :(得分:3)

@ sergio-tulentsev的回答很好。但是,我想指出你可以将yield包装在一个新的块中,从而传递给原始块的能力:

def withYield
  3.times { yield }
end
withYield {print "Go "}

要清楚,{ yield }是一个新块,它会传递给times。执行新块时,它会生成给{ print "Go" }原始 withYield块。原始块实际上并未传递给times,但是传递给原始块的能力,有效地让您调用原始块。

答案 2 :(得分:3)

为了完成这个主题,我想演示另一种调用原始块的技术:

def withProc
  p = Proc.new
  3.times(&p)
end
withProc { print "Go" }

Proc.new没有给出阻止时,它会使用withProc给出的阻止。现在你可以调用p,它将调用原始块。您也可以将p作为常规参数或块参数传递给times等其他方法。

有关更多讨论,请参阅https://medium.com/@amliving/proc-new-trick-c1df16185599