Возврат значения блока по Перечислению, когда не ноль - PullRequest
2 голосов
/ 10 ноября 2011

У меня немного странный вариант использования Ruby Enumerable, кажется.Я пытаюсь сделать что-то вроде следующего:

result = my_strategies.some_method do |strategy|
    strategy.get_result
end

Метод some_method является просто заполнителем, но является основой для остальной части этого вопроса.

Перечисляемая my_strategies содержит упорядоченный список стратегий для получения значения из удаленного сервиса;более предпочтительная стратегия запускается перед менее предпочтительной стратегией,

Иногда более предпочтительная стратегия потерпит неудачу, так что повторные попытки не будут корректными.В этом случае стратегия вернет ноль.

Я вижу способ сделать это, полагаясь на каждый блок, таким образом:

result = nil

my_strategies.each do |strategy|
    result = strategy.get_result
    if not r.nil?
        break
    end
end

Это кажется излишне шумным.Мне интересно, есть ли метод, который я могу заменить some_method для моего первого примера;что-то похожее на .any ?, но возвращаемое значение, из-за которого блок был истинным, вместо простого возврата true.

Альтернативные подходы к тому, что я пытаюсь сделать, также приветствуются.

РЕДАКТИРОВАТЬ: Первоначально я задал этот вопрос, потому что я пробовал этот блок кода:

result = my_strategies.find do |strategy|
    strategy.get_result
end

За исключением того, что это вернуло мне успешную стратегию, а не значение, которое он возвратил, когда это сделал,Меня не волнует, какая стратегия принесла мне ценность, я просто хочу знать, какова ценность.

Ответы [ 3 ]

7 голосов
/ 10 ноября 2011

Ваша потребность очень распространена, но, к сожалению, в ядре нет такой абстракции. Однако Facets парни давно определили этот пробел и внедрили Enumerable # find_yield (a.k.a Enumerable # map_detect ):

result = my_strategies.map_detect { |strategy| strategy.get_result }

Или просто: result = my_strategies.map_detect(&:get_result). В Ruby 2.0 реализованы отложенные перечислимые значения (для более ранних версий используйте enumerable-lazy ), поэтому теперь мы можем написать:

result = my_strategies.lazy.map(&:get_result).reject(&:nil?).first
1 голос
/ 10 ноября 2011

Вы можете использовать Enumerable#find для итерации по массиву, пока не получите свой результат:

result = nil

my_strategies.find do |strategy|
    result = strategy.get_result
end
0 голосов
/ 10 ноября 2011

Альтернативный подход к этому (без использования блока):

result = nil
num = 0

while result.nil?
  result = my_strategies[num].get_result
  num += 1
end
...