Вызывать следующий цикл 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` на основе статуса обработки.