2015-02-06 2 views
1

Я ожидал, что Enumerable#inject будет возвращать перечислитель, как и другие методы, и передавал ему блок; но это была ошибка. Пробовал следующее pry:Почему Ruby не вводит возвратный счетчик?

>> numbers = (1..12) 
=> 1..12 
>> numbers.each_with_index 
=> #<Enumerator: ...> 
>> numbers.each_with_index.map 
=> #<Enumerator: ...> 
>> numbers.inject(0) 
TypeError: 0 is not a symbol 
from (pry):18:in `inject' 

я ожидал, чтобы использовать его следующим образом:

numbers = (1..12) 
block = lambda { |sum, digit| sum + digit } 

numbers.inject(0) { |sum, digit| sum + digit } # => 78 
numbers.each_with_index.map &block # => [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23] 
numbers.inject(0) &block # => 0 is not a symbol (TypeError) 

Есть ли какая-то причина для такой реализации?

+1

Хороший вопрос. Раньше я об этом не думал. Обратите внимание, что существует довольно много методов «Enumerable», которые могут принимать блок, но не возвращают перечислитель, если не заданы. Другие включают 'count',' max', 'min',' minimax', 'none?' 'One?' И 'sort'. Я вижу общность во всех них, в том числе «уменьшать/внедрять». –

+0

Спасибо @CarySwoveland! Я довольно озадачен, почему они решили реализовать его так. Я почему-то не покупаю понятие о том, что его, потому что почти нет вариантов использования для его дальнейшего соединения. Я бы предположил, что согласованность могла бы быть лучше. –

+1

«Перечислитель» вычисляется по одному значению за раз. Вы можете немного потянуть (вызывая «next»), и одно значение выпадает. Вы снова тянете, другое значение выпадает. 'inject' не может этого сделать. –

ответ

5

Концептуально Enumerator - это тип коллекции. Enumerable#inject накапливает значение для членов коллекции, поэтому нет смысла возвращать Enumerator.

Вы можете получить работу, изменив numbers.inject(0) &block на:

numbers.inject(0, &block) 
+0

Не знал, была ли разница между двумя способами вызова! Я принимал блок, если он будет передан, если метод найдет его. –

+0

Это потому, что определение 'inject' имеет блок как аргумент, а другие могут использовать выход для вызова блока? –

1

Весь смысл методов, как inject это вернуть некоторую расчетную величину, основанную на счетчику. Если они всегда возвращают счетчик, не будет никакого значимого использования. Причина, по которой он возвращает перечислитель, когда блок отсутствует, - это позволить вам создать новый счетчик, изменив ресивер. Однако это не должно быть конечной целью; вы создаете только перечислитель, чтобы в итоге вы могли вычислить что-то на этом основании.

+0

Вы уверены, что вернули счетчик, если нет блока? Например, '[1,2,3] .reduce => LocalJumpError: никакого блока не задано'. –

+0

@CarySwoveland Я имел в виду для счетчиков. – sawa

 Смежные вопросы

  • Нет связанных вопросов^_^