2010-01-05 10 views
8

que estoy tratando de conseguir alrededor de un problema con el archivo: consultar/1 no permiten tuplas con la diversión en ellos como en este ejemplo:Convertir una cadena en un divertido

{add_one, fun(X) -> X+1 end}. 

Para evitar esto estoy considerando escribir la diversión dentro de una cadena y evaluarla

{add_one, "fun(X) -> X+1 end"}. 

La pregunta es. ¿Cómo convierto la cadena en una diversión?

+5

Para convertir una cadena en una diversión, cargue una broma en ella :-) –

Respuesta

11
parse_fun_expr(S) -> 
    {ok, Ts, _} = erl_scan:string(S), 
    {ok, Exprs} = erl_parse:parse_exprs(Ts), 
    {value, Fun, _} = erl_eval:exprs(Exprs, []), 
    Fun. 

Tenga en cuenta que necesita un punto al final de su expresión divertida, p. Ej. S = "fun(X) -> X + 1 end.".

+0

Absolutamente brillante. Gracias. –

0

Tal vez mediante el uso de erl_evalmodule?

+0

Sí, eso me llevó a eso. Sin embargo, no estoy seguro de cómo usarlo. Toma expresiones generadas por erl_parse pero al usar erl_parse generalmente termino con una expresión de una cadena. –

2

Me gustaría señalar que la respuesta de Zed crea una diversión interpretada. Cuando se llama a la diversión, ingresa al evaluador, que comienza a evaluar el árbol de sintaxis abstracta devuelto por erl_parse:parse_exprs/1 que ha capturado. En cuanto a la diversión creado:

11> erlang:fun_info(Fun, env). 
{env,[[],none,none, 
     [{clause,1, 
       [{var,1,'X'}], 
       [], 
       [{op,1,'+',{var,1,'X'},{integer,1,1}}]}]]} 
12> erlang:fun_info(Fun, module). 
{module,erl_eval} 

Uno puede ver que se ha cerrado sobre el árbol de sintaxis abstracta analizada como se ve en la env información, y es una diversión creado dentro erlang_eval como se ve en la module información.

Es posible usar el compilador erlang para crear un módulo compilado en tiempo de ejecución, y un puntero hacia eso es compile:forms/2 y code:load_binary/3. Pero los detalles de eso probablemente deberían ir a otra pregunta de stackoverflow.

+1

Gracias por señalar eso. Aquí hay un ejemplo de compilación de formularios: http://stackoverflow.com/questions/1974236/string-to-abstract-syntax-tree. – Zed

6

file:script/1 casi hace lo que quiere - evalúa una serie de expresiones de erlang de un archivo y devuelve el último resultado. Puede usarlo en lugar del file:consult/1, pero deberá cambiar el formato del archivo de "término. Término. Término". dando [term, term ,term] a "[término, término, término]". dando [term, term, term] - coloque una sola expresión en el archivo en lugar de una secuencia.

+1

Creo que esta es una mejor solución. Si hay una función de biblioteca que hace lo que quieres, entonces debes usarla. También analiza cadenas cuando no necesita parecer un poco apagado. – rvirding

+0

Ahh. Puedo considerar hacer eso en su lugar. Tenía mi cabeza tan atrapada en el archivo: consulte que olvidé considerar alternativas en esa parte. –

+0

Una pregunta adicional sin embargo. ¿Cómo puedo usar registros en el archivo: script? –

0
2> F =fun(Str,Binding) -> 
{ok,Ts,_} = erl_scan:string(Str), 
Ts1 = case lists:reverse(Ts) of 
      [{dot,_}|_] -> Ts; 
      TsR -> lists:reverse([{dot,1} | TsR]) 
     end, 
{ok,Expr} = erl_parse:parse_exprs(Ts1), 
erl_eval:exprs(Expr, Binding) end. 
#Fun<erl_eval.12.111823515> 
3> F("A=23.",[]). 
{value,23,[{'A',23}]} 

5> F("12+B.",[{'B',23}]). 
{value,35,[{'B',23}]} 
Cuestiones relacionadas