Enumerable
имеет first
:
(3..5).to_enum.first
# => 3
но у него нет last
:
(3..5).to_enum.last
# => NoMethodError: undefined method `last' for #<Enumerator: 3..5:each>
Почему это?
Enumerable
имеет first
:
(3..5).to_enum.first
# => 3
но у него нет last
:
(3..5).to_enum.last
# => NoMethodError: undefined method `last' for #<Enumerator: 3..5:each>
Почему это?
Это потому, что не все перечислимые объекты имеют последний элемент.
Простейшим примером может быть:
[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]
Даже если элементы перечисления конечны, нет простого способа получить последний элемент, отличный от итерации до конца, что было бы крайне неэффективно.
Поскольку не все Enumerable
имеют последний элемент, и это может быть или не быть, потому что Enumerable
не содержит элемента.
Рассмотрим следующий Enumerable
:
a = Enumerator.new do |yielder|
while true
yielder << 1
end
end
Это бесконечное Enumerable
.
Enumerable
является механизмом для итерации последовательности элементов. Для некоторых процессов итерации это может выполняться только один раз. Чтобы получить последний элемент (если он есть на самом деле один), он должен оценить весь процесс итерации и получить последний. После этого Enumerable
недействителен.
Единственная причина, по которой я могу думать, - это Enumerable
может быть бесконечным потоком.
infinity = Float::INFINITY
range = 1..infinity
range.to_enum.first
# => 1
range.to_a.last # will never finish
Я не согласен с мнением, что не все 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
на массив, что приводит к бесконечному циклу.
Смотрите ссылку (цикл) и ссылку (каждая) для небольшого выполнения кода для наблюдения за тем, что я хочу сказать.