2011-07-28 11 views
6

Tengo un código que necesito usar dentro de eval. A veces necesito salir del código de evaluación, pero mis intentos conducen a errores.ruby ​​- ¿Cómo regresar desde el interior de eval?

ej .:

# 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 

he intentado con return, end, exit, break, y no pude conseguir el éxito. exit no plantea errores, pero entonces no reciben la

5.

(Nota:. Sé que eval es malo, pero en este caso tengo que usarlo)

+0

Descubrí algo raro. 'break' salta de un bloque' yield'ed. Entonces, puedo hacer: 'def do_yield; rendimiento; fin; do_yield {eval "puts 1; puts 2; break; puts 3"}; pone 5' y obtengo el resultado esperado. ¡No sé por qué funciona eso! –

Respuesta

4

Gracias a todos, pero he encontrado una solución que se adapta mejor a mi problema:

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

De esta manera el return intuitiva de palabras clave se puede utilizar dentro eval para salir de ella con éxito.

No me gustaron las soluciones tipo condicional en este caso porque me obligaría (o al usuario) a agregar un end al final.

Sobre el uso de throw/catch o break, considero que la palabra clave return es más intuitiva.

2

es posible que utilices condicionales en lugar de retornos tempranos.

3

código evaluado se acaba de ejecutar en este lugar. No es una función o bloque. ¿Cómo lo harías sin eval? Probablemente así:

puts 1 
puts 2 
if(conditionFor3And4) 
    puts 3 
    puts 4 
end 
3

usted Can not. Puede volver a los métodos y salir de bloques o bucles, pero no evaluar.

Usted podría tratar de un bloque de tiro/catch lugar

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

o esto:

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

o simplemente hacer un condicional como MCHL dijo, ya que probablemente quiere que parada condicional, no sólo siempre, pero throw catch te permitirá saltar de un bloque sin importar cuántos niveles abajo estés, lo que lo hace más robusto, si necesitas salir de un bucle anidado o algo así.

+1

¡Respuesta impresionante! De esta forma puedo poner 'catch: stop do ... end' __around__' eval' y usar solo' throw' dentro de él! Antes de su respuesta, estaba pensando en usar 'Continuación', pero' catch/throw' es mucho mejor porque no involucra variables globales cc, solo símbolos. –

+0

No me di cuenta pero es genial, puedes ponerlos al lado del bloque eval. Whoa. – loosecannon

Cuestiones relacionadas