В рубина мы можем сделать что-то вроде:Руби Enumerable: первое truthy значение блока
stuff_in_trash.detect(&:eatable?)
=> :pack_of_peanuts
stuff_in_trash.detect(&:drinkable?)
=> nil
Но что, если мы заинтересованы в значении блока в первый раз это truthy, а не первый элемент, для которого блок имеет истинное значение?
Это конвертировать следующий код:
def try_to_make_artwork_from(enumerable)
enumerable.each do |item|
result = make_artwork_from item
return result if result
end
nil
end
Чтобы что-то вроде:
def try_to_make_artwork_from(enumerable)
enumerable.try_with { |item| make_artwork_from item }
end
Что желательно в исходном коде:
- возвращает
nil
если блок никогда не требует правдивой ценности; - Он возвращает значение блока в первый раз, когда он правдивый;
- Он останавливается после нахождения первого матча;
- Это еще не звонок
make_artwork_from
(скажем, он не может возвратить тот же результат при следующем его вызове).
Что не так желательно, это то, что использует result
три раза, но это не имеет ничего общего с историей.
EDIT: Извините, первоначальная реализация была неправильной, необходимо было вернуть nil
в случае, когда значение блока никогда не было истинным.
enumerable.lazy.map(&:block).detect(&:itself)
выполняет эту работу, но является самым простым способом? Эффективно ли сравнение с использованием each
и кэширование значения?
Что вы имеете в виду под «значением блока ", вы имеете в виду аргумент, переданный блоку или возвращаемый блок? Может быть, мне что-то не хватает, но это не цель ['Enumerable # find'] (http://ruby-doc.org/core-2.4.0/Enumerable.html # method-i-find) – Anthony
Возможно, это только я, но я не понимаю ваш вопрос. Не будет 'enumerable.detect {| item | make_artwork_from (item)} 'точно возвращает желаемый результат? – spickermann
@spickermann OP хочет, чтобы метод возвращал значение 'make_artwork_from (item)'. Ваш код выше вернет значение 'item'. –