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?
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 Enumerable
s 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.