Enumerable
有first
:
(3..5).to_enum.first
# => 3
但它没有last
:
(3..5).to_enum.last
# => NoMethodError: undefined method `last' for #<Enumerator: 3..5:each>
为什么?
答案 0 :(得分:13)
这是因为并非所有可枚举对象都具有最后一个元素。
最简单的例子是:
[1, 2, 3].cycle
# (an example of what cycle does)
[1,2,3].cycle.first(9) #=> [1, 2, 3, 1, 2, 3, 1, 2, 3]
即使枚举器元素是有限的,也没有简单的方法来获取最后一个元素而不是迭代它到最后,这将是非常低效的。
答案 1 :(得分:6)
因为并非所有Enumerable
都有最后一个元素,这可能会也可能不会,因为Enumerable
不包含任何元素。
考虑以下Enumerable
:
a = Enumerator.new do |yielder|
while true
yielder << 1
end
end
这是一个无限的Enumerable
。
Enumerable
是一种迭代元素序列的机制。对于某些迭代过程,这可能只执行一次。为了获得最后一个元素(如果实际存在一个元素),它必须评估整个迭代过程并获得最后一个元素。之后,Enumerable
无效。
答案 2 :(得分:1)
我能想到的唯一原因是Enumerable
s可能是无限流。
infinity = Float::INFINITY
range = 1..infinity
range.to_enum.first
# => 1
range.to_a.last # will never finish
答案 3 :(得分:-1)
我不同意不是所有Enumerable
都有最后一个要素的意见。我认为在回复Enumerator
方法时,很少loop
个方法无法结束to_a
。这就是Enumerable
确定第一个元素的原因,但是他们无法确定它的最后一个元素。
Enumerator#each
each_enum = (0..1).each
#=> #<Enumerator: 0..1:each>
each_enum.to_a
#=> [0, 1]
而
Enumerator#cycle
cycle_enum = (0..1).cycle
#=> #<Enumerator: 0..1:cycle>
cycle_enum.to_a
继续将next
元素推入数组,导致无限循环。
请参阅此link(cycle)和此link(each),以便执行少量代码,以观察我想说的内容。