[朋友,请提供有关以下解释的帮助:在下面的Ruby代码中,什么条件限制了循环的作用?它应该是一个无限循环,但是,它如何终止?
# Ruby code
fib = Enumerator.new do |y|
a = b = 1
loop do
y << a
a, b = b, a + b
end
end
p fib.take(10) # => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
您的贡献将受到高度赞赏。
((来源:https://rossta.net/blog/infinite-sequences-in-ruby.html)
您已实现功能fib
的方式使其“懒惰”。这意味着Ruby在绝对必要之前不会尝试计算fib
中的值。
最后一行的take
方法是这里的关键。
p fib.take(10)
[基本上,Ruby说:“我将评估fib
的前10个值,并假装其余的值不存在,因为我还必须不使用它们。”
换句话说,虽然fib
函数确实是无限的,但您只要求输入前10个值,所以您只获得了前10个值。
如果您尝试过类似的操作:
p fib.to_a
您的程序会卡住。为什么?因为to_a
(到数组)方法想要尝试获取[[all fib的值,而不仅仅是其中的几个。显然,您无法获得无限列表的all值。
枚举器的一种类型与对象的基础集合相关联。这是两个与数组绑定的对象。
enum = [1,2,3].each #=> #<Enumerator: [1, 2, 3]:each>
enum.next #=> 1
enum.next #=> 2
enum.next #=> 3
enum.next #=> StopIteration (iteration reached an end)
enum = [1,2,3].cycle #=> #<Enumerator: [1, 2, 3]:cycle> enum.next #=> 1 enum.next #=> 2 enum.next #=> 3 enum.next #=> 1 enum.next #=> 2 ... ad infinitum enum.first(8) #=> [1, 2, 3, 1, 2, 3, 1, 2]
在第一个示例中,在引发StopIteration
异常之前,枚举器仅生成有限数量的对象。在第二个示例中,可以生成任意数量的对象,但只能生成on demand。例如,
另一种类型的枚举器根据它所固有的一组规则生成对象,这些规则不与基础对象绑定。这些枚举器通常能够生成无限数量的对象。生成斐波那契数的枚举器就是这种枚举器的一个示例。这不是一个不会终止的循环。它是一台能够按需生产任意数量但每次只能生产一个物体的机器。first(8)
指示enum
生成并传递给自身的8
对象。enum
不是lazy;所有人都渴望遵守,但除非得到指示,否则不会制造和分配糖果或其他东西。