Ruby枚举器如何终止迭代?
朋友们,请帮我解释一下:在下面的Ruby代码中,白蚁循环的作用是什么?它应该是一个无限循环,但是,它是如何终止的呢Ruby枚举器如何终止迭代?,ruby,enumerable,enumerator,take,Ruby,Enumerable,Enumerator,Take,朋友们,请帮我解释一下:在下面的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] #Ruby代码 fib=枚举数。新do | y
# 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]
#Ruby代码
fib=枚举数。新do | y|
a=b=1
环道
y[1,1,2,3,5,8,13,21,34,55]
非常感谢您的贡献。(来源:)
您实现函数fib的方式允许它“懒惰”。这意味着Ruby在绝对必要之前不会尝试计算fib中的值
最后一行的take
方法是这里的关键
p fib.take(10)
基本上,Ruby说“我将评估fib
的前10个值,并假装其余的值不存在,因为我还不必使用它们。”
换句话说,虽然fib
函数可能是无限的,但您只要求前10个值,因此您只得到了前10个值
如果您尝试过类似的方法:
p fib.to_a
你的程序会被卡住。为什么?因为to_a
(to array)方法想要尝试获取所有fib的值,而不仅仅是其中的一部分。显然,您无法获得无限列表的所有值
有关更多信息:
---编辑:---
技术修正:正如Cary Swoveland指出的那样,如果说fib
是一种按需生成值的算法/机器,那么在技术上更为正确 枚举器就像一个按钮,每次按下分配器顶部时,它都会弹出一颗薄荷糖。计数型的自动售货机不会供应糖果,但会根据需要一次生产一种糖果,可能能够生产无限数量的糖果
一种类型的枚举数绑定到底层对象集合。这里有两个绑定到一个数组
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]。每个#=>
enum.next#=>1
enum.next#=>2
enum.next#=>3
enum.next#=>停止迭代(迭代已结束)
enum=[1,2,3]。循环#=>#
enum.next#=>1
enum.next#=>2
enum.next#=>3
enum.next#=>1
enum.next#=>2
... 无限远
枚举第一(8)
#=> [1, 2, 3, 1, 2, 3, 1, 2]
在第一个示例中,在引发StopIteration
异常之前,枚举器只生成有限数量的对象。在第二个示例中,可以生成任意数量的对象,但只能根据需要生成<例如,code>first指示enum
8次生成一个对象并将其传递给自身<代码>枚举
不懒惰;它渴望遵守,但在得到指示之前不会制造和分发物品
另一种类型的枚举器根据一组与生俱来的规则生成对象,这些规则与基础对象无关。这些枚举器通常能够生成无限多个对象。生成斐波那契数的枚举数就是该类型枚举数的一个示例。它不是一个不终止的循环;它是一种能够根据需要生产任意数量的物体,但一次只能生产一个物体的机器 另一方面,在Ruby v2.7中,Ruby monks赋予了我们一种方法,它简化了一些枚举数的创建,包括生成斐波那契数的枚举数:
enum=Enumerator.product([0,1]){n1,n2 |[n2,n2+n1]}
。例如,前8个斐波那契数由arr=enum.take(8)#=>[[0,1]、[1,1]、[1,2]、[2,3]、[3,5]、[5,8]、[8,13]、[13,21]
给出,然后是arr.map(&:first)#=>[0,1,1,2,3,5,8,13]
。
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]