我正在尝试解决文件问题:咨询/ 1不允许元组在其中有趣,如下例所示:
{add_one, fun(X) -> X+1 end}.
为了解决这个问题,我正在考虑在字符串中编写乐趣并对其进行评估
{add_one, "fun(X) -> X+1 end"}.
问题是。如何将字符串转换为有趣的?
答案 0 :(得分: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.
请注意,您需要在乐趣表达结束时使用句号,例如: S = "fun(X) -> X + 1 end."
。
答案 1 :(得分:6)
file:script/1
几乎可以做你想要的 - 它从文件中计算一系列erlang表达式并返回最后的结果。您可以使用它代替file:consult/1
,但您需要从“term.term.term”更改文件的格式。将[term, term ,term]
提供给“[term,term,term]。”给[term, term, term]
- 在文件中放置一个表达式而不是序列。
答案 2 :(得分:2)
我想指出,Zed的回答创造了一种解释乐趣。当调用fun时,它进入评估器,评估器开始评估它捕获的erl_parse:parse_exprs/1
返回的抽象语法树。看看创造的乐趣:
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}
可以看到它已经关闭了解析后的抽象语法树,如env
信息中所示,并且在module
信息中看到的erlang_eval内部创建了一个有趣的乐趣。
可以使用erlang编译器在运行时创建编译模块,指向它的指针是compile:forms/2和code:load_binary/3。但其中的细节可能会进入另一个stackoverflow问题。
答案 3 :(得分:0)
也许可以使用erl_eval
module ?
答案 4 :(得分: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}]}