Почему `Enumerable` имеет` first`, но не `last`?

Enumerable имеет first:

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

но у него нет last:

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

Почему это?

Ответ 1

Это потому, что не все перечислимые объекты имеют последний элемент.

Простейшим примером может быть:

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

Даже если элементы перечисления конечны, нет простого способа получить последний элемент, отличный от итерации до конца, что было бы крайне неэффективно.

Ответ 2

Поскольку не все Enumerable имеют последний элемент, и это может быть или не быть, потому что Enumerable не содержит элемента.

Рассмотрим следующий Enumerable:

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

Это бесконечное Enumerable.

Enumerable является механизмом для итерации последовательности элементов. Для некоторых процессов итерации это может выполняться только один раз. Чтобы получить последний элемент (если он есть на самом деле один), он должен оценить весь процесс итерации и получить последний. После этого Enumerable недействителен.

Ответ 3

Единственная причина, по которой я могу думать, - это Enumerable может быть бесконечным потоком.

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

range.to_enum.first
# => 1

range.to_a.last # will never finish

Ответ 4

Я не согласен с мнением, что не все 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 на массив, что приводит к бесконечному циклу.

Смотрите ссылку (цикл) и ссылку (каждая) для небольшого выполнения кода для наблюдения за тем, что я хочу сказать.