将字符串转换为 fun

发布于 2024-08-16 18:07:26 字数 242 浏览 5 评论 0原文

我试图解决 file:consult/1 不允许元组中包含 fun 的问题,如下例所示:

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

为了解决这个问题,我正在考虑在字符串中写入 fun 并对其进行评估

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

问题是。如何将字符串转换为有趣的字符串?

I'm trying to get around a problem with file:consult/1 not allowing tuples with fun in them like in this example:

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

To get around this I'm considering writing the fun inside a string and evaluating it

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

The question is. How do I convert the string into a fun?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

酒解孤独 2024-08-23 18:07:26
parse_fun_expr(S) ->
  {ok, Ts, _} = erl_scan:string(S),
  {ok, Exprs} = erl_parse:parse_exprs(Ts),
  {value, Fun, _} = erl_eval:exprs(Exprs, []),
  Fun.

请注意,您的 fun 表达式末尾需要有一个句点,例如 S = "fun(X) -> X + 1 end."

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

Note that you need a period at the end of your fun expression, e.g. S = "fun(X) -> X + 1 end.".

蓝眼泪 2024-08-23 18:07:26

file:script/1 几乎可以满足您的需求 - 它从文件中计算一系列 erlang 表达式并返回最后的结果。您可以使用它来代替 file:consult/1,但您需要将文件的格式从“term.term.term”更改为“term.term.term”。将 [term, term ,term] 赋予“[term, term , term]”。给出[term, term, term] - 在文件中放置单个表达式而不是序列。

file:script/1 almost does what you want - it evaluates a series of erlang expressions from a file and returns the last result. You could use it in place of file:consult/1 but you'd need to change the format of the file from "term. term. term." giving [term, term ,term] to "[term, term , term]." giving [term, term, term] - place a single expression in the file instead of a sequence.

╰ゝ天使的微笑 2024-08-23 18:07:26

我想指出的是,泽德的回答创造了一种解释性的乐趣。当 fun 被调用时,它进入评估器,评估器开始评估它捕获的 erl_parse:parse_exprs/1 返回的抽象语法树。查看创建的 fun:

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 信息中所示,并且它是在 erlang_eval 内部创建的 fun,如 module< 中所示。 /代码> 信息。

可以使用 erlang 编译器在运行时创建编译模块,指向该模块的指针是 compile:forms/2代码:load_binary/3。但其细节可能应该进入另一个 stackoverflow 问题。

I'd like to point out that Zed's answer creates an interpreted fun. When the fun is called it enters the evaluator which starts to evaluates the abstract syntax tree returned by erl_parse:parse_exprs/1 that it has captured. Looking at the fun created:

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}

One can see that it has closed over the parsed abstract syntax tree as seen in the env info, and it is a fun created inside erlang_eval as seen in the module info.

It is possible to use the erlang compiler to create a compiled module at runtime, and a pointer toward that is compile:forms/2 and code:load_binary/3. But the details of that should probably go into another stackoverflow question.

末蓝 2024-08-23 18:07:26

也许通过使用 erl_eval 模块

Maybe by using the erl_eval module?

人间☆小暴躁 2024-08-23 18:07:26
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}]}
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}]}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文