2016-12-09 4 views
3

У меня есть ленивая оценка, где мне нужен первый правдивый результат, полученный в результате операции с картой, и еще раз я обнаружил, что нахожусь в конце своего выражения .find { |e| e }.Ruby: Можно ли использовать для выбора/поиска без блока?

Вот простой пример; массив и карта блока являются, конечно же, отличается в моей реальной жизни:

[nil, 2, 3, 4].lazy.map{ |e| e }.find { |e| e } 

Я всегда немного удивлен/разочарование, когда я должен добавить блок { |e| e } к select или find, особенно если это ленивые вычисления, потому что оба - избыточно - кажется, функции тождественные по умолчанию:

> [nil, 2, 3, 4].find { |e| e } 
=> 2 
> [nil, 2, 3, 4].find 
=> #<Enumerator: [nil, 2, 3, 4]:find> 
> [nil, 2, 3, 4].find.map { |e| e } 
=> [nil, 2, 3, 4] 

ли это Enumerator практически отличаются вообще от полученного от .each?

> [nil, 2, 3, 4].each.map { |e| e } 
=> [nil, 2, 3, 4] 

Аналогично с select, за исключением того, что еще более бесполезным с ленивым:

> [nil, 2, 3, 4].select 
=> #<Enumerator: [nil, 2, 3, 4]:select> 
> [nil, 2, 3, 4].select { |e| e } 
=> [2, 3, 4] 
> [nil, 2, 3, 4].select.lazy.force # doing it wrong looks functional! 
=> [nil, 2, 3, 4] 
> [nil, 2, 3, 4].lazy.select { |e| e }.force 
=> [2, 3, 4] 
> [nil, 2, 3, 4].lazy.select.force # same without .force 
ArgumentError: tried to call lazy select without a block 

Являются ли эти очевидные тождества полезны, или просто возможность для лучшего по умолчанию в будущей версии (и ArgumentError!) Рубин?

+0

'cycle' без блока возвращает перечислитель, бесконечно петли (т.е.' next' может быть применен на неопределенный срок), так что немного отличается от других. –

ответ

2

Прежде всего - небольшое примечание. Если вы когда-нибудь набрали { |e| e }, вместо этого вы можете использовать &:itself.

С учетом этого, перечисляемые методы без блока часто возвращают счетчик. Вы можете использовать это для цепочки с помощью методов перечислителя. Например, рассмотрим:

[1, 2, 3].map.with_index { |n, i| n + i } # => [1, 3, 5] 
[1, 2, 3].each.with_index { |n, i| n + i } # => [1, 2, 3] 

[1, 2, 3].select.with_index { |n, i| (n + 2 * i).even? } # => [2] 
+0

Хорошо, но поскольку ОП запросил специально для выбора, вы можете показать пример с помощью select. – tokland

+0

@tokland, добавлено. – ndn

+0

Мм, спасибо за быстрый ответ. 'select.with_index {| _, i | i> 2} 'имеет смысл, но он не работает с ленивым, что кажется немного дырой. Спасибо за ссылку на '(&: self)' - интересную и, вероятно, более эффективную, но не столь ясную, как '{| e | e} 'в мой мозг. :) –

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