ruby - Как вернуться изнутри eval? - PullRequest
6 голосов
/ 28 июля 2011

У меня есть код, который мне нужно использовать в eval. Иногда мне нужно выйти из кода eval, но мои попытки приводят к ошибкам.

например:.

# expected to see 1, 2 and 5; not 3 nor 4; and no errors
eval "puts 1; puts 2; return; puts 3; puts 4"   # => Error: unexpected return
puts 5

Я пробовал с return, end, exit, break, и не смог добиться успеха. exit не вызывает ошибок, но тогда я не получаю 5.

(Примечание: я знаю, что eval является злом, но в этом случае мне нужно его использовать.)

Ответы [ 5 ]

4 голосов
/ 29 июля 2011

Спасибо всем, но я нашел решение, которое лучше всего подходит для моей проблемы:

lambda do
  eval "puts 1; puts 2; return; puts 3; puts 4"
end.call
puts 5

Таким образом, интуитивно понятное ключевое слово return можно использовать внутри eval, чтобы успешно выйти из него.

Мне не понравились условно-подобные решения в этом случае, потому что это заставило бы меня (или пользователя) добавить end в конце.

Об использовании throw/catch или break я считаю ключевое слово return более интуитивным.

3 голосов
/ 28 июля 2011

eval'd код просто запускается в этом месте.Это не функция или блок.Как бы вы сделали это без Eval?Вероятно, так:

puts 1
puts 2 
if(conditionFor3And4) 
  puts 3 
  puts 4
end
3 голосов
/ 28 июля 2011

Вы не можете. Вы можете вернуться из методов и выйти из блоков или циклов, но не eval.

Вместо этого вы можете попробовать бросить / поймать блок

eval " 
  should_stop = true
  catch :stop do
    puts 1  
    puts 2 
    throw :stop if should_stop
    puts 3
  end
"

или это:

  should_stop = true
  catch :stop do
  eval " 
    puts 1  
    puts 2 
    throw :stop if should_stop
    puts 3
 "
 end

или просто сделайте условное, как сказал Мчл, так как вы, вероятно, хотите, чтобы он был условно остановлен, а не только всегда, но бросок catch позволит вам выпрыгнуть из блока независимо от того, на сколько уровней вы находитесь ниже, что сделает его более устойчивым , если вам нужно вырваться из вложенного цикла или что-то в этом роде.

2 голосов
/ 28 июля 2011

Вы можете просто использовать условные выражения вместо ранних возвратов.

0 голосов
/ 28 марта 2018

Вы вполне можете определить функцию и выполнить ее последним в конце скрипта следующим образом:

def ev(s)
  eval("def doStuff()\n" + s + "\nend\ndoStuff()")
end

ev("
    1
    return 2
    3
")

#=> 2

Демо

...