我最近开始读“编程Ruby1.9&2.0”一书。它展示了显式枚举器的一个技巧。
triangular_numbers = Enumerator.new do |yielder|
number = 0
count = 1
loop do
number += count
count += 1
yielder.yield number
end
end
5.times { print triangular_numbers.next, " " }
puts我想知道为什么这个yielder.yield会暂时离开循环,并且返回数字的值,直到下一个枚举器对象创建。这似乎不同于通常情况下,当一个屈服在循环块内。我检查了APIdock,发现Proc.yield()的源代码与Proc.call()相同。对于枚举器类中的伊阿尔德对象,伊阿尔德重写了产程()。但是为什么yielder.yield会暂时离开循环块呢?
参考资料:APIdock产量(),打电话
发布于 2013-09-18 13:50:21
您混淆了Ruby的产额语句和枚举数::收益法和Proc的屈服法。它们可能拼写相同,但它们完全不同。
语句
收益声明没有接收者。在一个方法中,它的意思是“立即运行这个块”。如果没有附加块,则会发生错误。它并不总是给出一个论点,因为有时候你只是想运行这个块。
def foo
yield :bar
end
foo # LocalJumpError
foo { |x| puts x } # bar枚举者::
作为一个让步者,yield几乎总是被给予一个论点。这是因为它的意思与<<相同,即“下次有人在我身上调用next时,给他们这个值”。
Enumerator.new { |yielder| yielder.yield 3 }.next # 3
Enumerator.new { |yielder| yielder << 3 }.next # same thing我认为使用<<来避免与收益语句混淆是个好主意。
流程
Procs和lambdas基本上是功能。yield在这里的意思与call相同,后者“只需调用函数”。您可以为它提供一个参数,这取决于proc是如何定义的。这里没什么花哨的。
proc { |x| puts x }.yield(:bar) # bar
proc { |x| puts x }.call(:bar) # same thing as previous line我认为使用call来避免与收益语句混淆是个好主意。
发布于 2014-06-13 05:35:59
我在书中也偶然发现了这个例子。在思考了示例如何工作和浏览Ruby之后,我找到了纤维类,我认为它是场景后面的枚举器所使用的:
http://www.ruby-doc.org/core-2.0/Fiber.html
光纤概念实现了“轻量级协作并发”,这是非常有趣的,并不是很难理解,更重要的是,它不同于其他调用块或处理线程控件的“产量”。
我认为枚举器有一个光纤对象,它在其中传递给块。然后看起来就像每次在枚举数上调用" next“时,它都会调用纤对象上的”恢复“以允许它计算下一个数字,而当块调用光纤上的”产生“时,该控件返回到"next”方法。诸若此类。
下面是我可能实现枚举器的版本(当然,只有在本书示例中讨论的部分):
class MyExplicitEnumerator
def initialize (&block)
@yielder = Fiber.new { block.call Fiber }
end
def next
@yielder.resume
end
end
e = MyExplicitEnumerator.new do |yielder|
number = 1
loop do
yielder.yield number
number += 1
end
end
p e.next
p e.next
# output
# 1
# 2https://stackoverflow.com/questions/18865860
复制相似问题