Вызывать следующий цикл ruby из внешнего метода
в Ruby легко указать цикл, чтобы перейти к следующему элементу
(1..10).each do |a|
next if a.even?
puts a
end
result = >
1
3
5
7
9
но что, если мне нужно вызвать следующий извне цикла (например: метод)
def my_complex_method(item)
next if item.even? # this will obviously fail
end
(1..10).each do |a|
my_complex_method(a)
puts a
end
Единственное решение, которое я нашел и работает, - это использовать throw
и catch
как в вопросе SO Как нарушить внешний цикл в Ruby?
def my_complex_method(item)
throw(:skip) if item.even?
end
(1..10).each do |a|
catch(:skip) do
my_complex_method(a)
puts a
end
end
Мой вопрос: кто-нибудь получил более дешевое решение для этого? или throw/catch
только для этого?
И что, если я хочу называть my_complex_method
не только как часть этого цикла (= > не бросать: skip), могу ли я как-то сказать мой метод, который он вызвал из цикла?
Ответы
Ответ 1
Сложный метод может возвращать логическое значение, а затем вы сравниваете свой цикл следующим образом:
def my_complex_method(item)
true if item.even?
end
(1..10).each do |a|
next if my_complex_method(a)
puts a
end
Простой подход, но отличный от try catch.
UPDATE
Поскольку item.even?
уже возвращает логическое значение, вам не нужна часть true if item.even?
, вы можете сделать следующее:
def my_complex_method(item)
item.even?
end
Ответ 2
Enumerator#next
и Enumerator#peek
будет хороший вариант для goo:
def my_complex_method(e)
return if e.peek.even?
p e.peek
end
enum = (1..5).each
enum.size.times do |a|
my_complex_method(enum)
enum.next
end
Выход
1
3
5
Ответ 3
Если вам нужно только выполнить действия только с некоторыми значениями, основанными на значении, возвращаемом my_complex_method
, вы можете использовать перечисления с умом:
(1..10).map { |a| [a, my_complex_method(a)] }.each do |a, success|
puts a if success
end
Вы можете определить метод принятия блока и предпринять некоторые действия в этом блоке на основе успеха или отказа там:
(1..10). Каждый do | a | my_complex_method {| success | next if success} конец
Благодаря определению масштаба вы можете не использовать `catch`/` throw` и вызывать `next` на основе статуса обработки.