我是Ruby的新手,有没有办法从Ruby函数中获取yield
值?如果有,怎么样?如果没有,我有什么选择来编写惰性代码?
答案 0 :(得分:48)
Ruby的yield
关键字与具有相同名称的Python关键字有很大不同,所以不要被它混淆。 Ruby的yield
关键字是用于调用与方法关联的块的语法糖。
最接近的等价物是Ruby的Enumerator类。例如,相当于Python:
def eternal_sequence():
i = 0
while True:
yield i
i += 1
就是这样:
def eternal_sequence
Enumerator.new do |enum|
i = 0
while true
enum.yield i # <- Notice that this is the yield method of the enumerator, not the yield keyword
i +=1
end
end
end
您还可以使用enum_for
为现有枚举方法创建枚举器。例如,('a'..'z').enum_for(:each_with_index)
为您提供小写字母的枚举器及其在字母表中的位置。您可以使用1.9中的each_with_index
等标准Enumerable方法免费获得此功能,因此您只需编写('a'..'z').each_with_index
即可获取枚举器。
答案 1 :(得分:23)
我已经看到Fibers以这种方式使用,请查看this article中的示例:
fib = Fiber.new do
x, y = 0, 1
loop do
Fiber.yield y
x,y = y,x+y
end
end
20.times { puts fib.resume }
答案 2 :(得分:12)
如果你想懒洋洋地产生价值,@ Chuck的回答是正确的。
如果你想懒洋洋地迭代一个集合,Ruby 2.0引入了新的.lazy
枚举器。
range = 1..Float::INFINITY
puts range.map { |x| x+1 }.first(10) # infinite loop
puts range.lazy.map { |x| x+1 }.first(10) # [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
答案 3 :(得分:5)
Ruby使用Enumerable::Generator
开箱即用地支持生成器:
require 'generator'
# Generator from an Enumerable object
g = Generator.new(['A', 'B', 'C', 'Z'])
while g.next?
puts g.next
end
# Generator from a block
g = Generator.new { |g|
for i in 'A'..'C'
g.yield i
end
g.yield 'Z'
}
# The same result as above
while g.next?
puts g.next
end
https://ruby-doc.org/stdlib-1.8.7/libdoc/generator/rdoc/Generator.html