質問

Enumerable has first:

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

but it does not have last:

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

Why is that?

役に立ちましたか?

解決

It is because not all enumerable objects have the last element.

The simplest example would be:

[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]

Even if the enumerator elements are finite, there is no easy way to get the last element other than iterating through it to the end, which would be extremely inefficient.

他のヒント

Because not all Enumerable has last element, and this may or may not because that the Enumerable contains no element.

Consider the following Enumerable:

a = Enumerator.new do |yielder|
  while true
    yielder << 1
  end
end

It's a infinite Enumerable.

Enumerable is a mechanism to iterate a sequence of elements. For some of the iterate process, this may only perform once. In order to get the last element (if there is actually one), it must evaluate the whole iterate process and get the last one. After that, the Enumerable is invalid.

The only reason I can think of is Enumerables may be infinite streams.

infinity = Float::INFINITY
range = 1..infinity

range.to_enum.first
# => 1

range.to_a.last # will never finish

I do not agree with opinion that not all Enumerable has last element. I think few Enumerator methods are unable to end the loop while responding to to_a method. That is why Enumerable knows first element for sure but they can not determine about its last element.

Enumerator#each
each_enum = (0..1).each
#=> #<Enumerator: 0..1:each> 
each_enum.to_a
#=> [0, 1] 

Whereas

Enumerator#cycle
cycle_enum = (0..1).cycle
#=> #<Enumerator: 0..1:cycle> 
cycle_enum.to_a

keeps on pushing next element into array resulting in infinite loop.

See this link(cycle) and this link(each) for few code execution to observe what I want to say.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top