为什么`Enumerable`有'first`而不是`last`?

时间:2014-03-20 01:58:32

标签: ruby enumerable

Enumerablefirst

(3..5).to_enum.first
# => 3

但它没有last

(3..5).to_enum.last
# => NoMethodError: undefined method `last' for #<Enumerator: 3..5:each>

为什么?

4 个答案:

答案 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),以便执行少量代码,以观察我想说的内容。