2010-03-17 21 views
8

Quiero definir el bloque como una cadena, luego creo la lambda. El siguiente ejemplo no funciona. ¿Es posible algo así?Crear un rubí Proc desde una cadena

code_string = "|x|x*2" 

l = lambda {eval(code_string)} 

l.call(3) => 6 
+1

no me refiero a sonar grosero, pero ¿por qué en el mundo quiere hacer esto? 'eval' casi nunca es la mejor manera de hacer algo, por el bien de la eficiencia, nada más. – Chuck

+0

Esto definitivamente parece bastante hacky –

+0

A veces necesitas generar código "sobre la marcha", a menudo de una fuente que no es el código de Ruby. Utilizo esta técnica para implementar un transpiler. –

Respuesta

7

Esto funciona

eval "lambda { " + code_string + " }" 

Sólo que no sé por qué esto se hace y el otro no lo hace.

+3

Llamar a lambda en un argumento eval resulta en un objeto Proc con la llamada eval 'dentro' del objeto Proc. El objeto Proc resultante no toma un argumento, ya que la expresión 'eval (code_string)' no toma un argumento. Cuando llamas al objeto Proc, ¡evalúa code_string! La evaluación de la cadena "lambda {" + code_string + "}" proporciona un objeto Proc que espera un argumento y devuelve 2 * argumento. – Fred

+4

Además, es más idiomático (y más eficiente para arrancar) utilizar la interpolación de cadenas, por lo que sería: 'eval 'lambda {# {code_string}}' '. La concatenación de varias cadenas con '+' rara vez se realiza en Ruby. – Chuck

0

eval "lambda {#{code_string}}"

Cuestiones relacionadas