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
определяет, например. map
или max
, с [1].cycle
тоже не работает. Почему last
особенный?
- person Victor Moroz; 20.03.2014
loop
.
- person Marc-André Lafortune; 20.03.2014
Enumeable
, такие как #to_a
, #min
, #all?
и #reduce
.
- person Matthew; 26.02.2021
Потому что не все Enumerable
имеют последний элемент, и это может быть или не быть, потому что Enumerable
не содержит элемента.
Рассмотрим следующее Enumerable
:
a = Enumerator.new do |yielder|
while true
yielder << 1
end
end
Это бесконечное Enumerable
.
Enumerable
— это механизм для повторения последовательности элементов. Для некоторых итерационных процессов это может выполняться только один раз. Чтобы получить последний элемент (если он действительно есть), он должен оценить весь итерационный процесс и получить последний элемент. После этого Enumerable
недействителен.
Единственная причина, о которой я могу думать, это то, что Enumerable
s могут быть бесконечными потоками.
infinity = Float::INFINITY
range = 1..infinity
range.to_enum.first
# => 1
range.to_a.last # will never finish
Float::INFINITY
может появиться как начальный элемент, и в этом случае first
вызовет ошибку, а не будет неопределенным: (Float::INFINITY..5).to_enum => #<Enumerator: Infinity..5:each>
. Но (Float::INFINITY..5).to_enum.first # => TypeError: can't iterate from Float
.
- person sawa; 20.03.2014
Я не согласен с мнением, что не все 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
в массив, что приводит к бесконечному циклу.
См. эту ссылку(цикл) и эту ссылка(каждая) для небольшого выполнения кода, чтобы наблюдать, что я хочу сказать.
cycle_enum
?
- person Sergio Tulentsev; 31.08.2016
Enumerable
тоже нетlast
- person Victor Moroz   schedule 20.03.2014Kernel#to_enum
, который генерируетEnumerator
, а неEnumerable
- person bjhaid   schedule 20.03.2014Enumerable
- person Victor Moroz   schedule 20.03.2014Enumerator
, который не имеетfirst
, но наследует его отEnumerable
. - person sawa   schedule 20.03.2014