【问题标题】:Erlang: how can I reference an anonymous function from within the body?Erlang:我如何从体内引用匿名函数?
【发布时间】:2014-05-20 20:16:20
【问题描述】:

Erlang有没有办法引用当前正在执行的函数)?

这对于产生无限循环很有用:

spawn(fun() -> do_something, this_fun() end)

在 JavaScript 中 arguments.callee 就是这样做的,请参阅 MDC 上的规范。

编辑回答“你为什么要这样做”:主要是好奇心;在原型设计时定义一个计时器也很有用:

Self = self(),
spawn(fun() -> Self ! wake_up, receive after 1000 -> nil end, this_fun() end),
%% ...

【问题讨论】:

标签: erlang


【解决方案1】:

在 Erlang/OTP 17.0-rc1 中,您可以为此使用命名 fun:

1> Self = self(),
1> Fun = fun ThisFun() ->
             Self ! wake_up,
             receive after 1000 -> nil end,
             ThisFun()
         end.
#Fun<erl_eval.44.71889879>
2> spawn(Fun).
<0.35.0>
3> flush().
Shell got wake_up
Shell got wake_up
Shell got wake_up
ok

在早期版本中,无法做到这一点。您可以将函数本身作为参数传递:

Self = self(),
Fun = fun(ThisFun) ->
          Self ! wake_up,
          receive after 1000 -> nil end,
          ThisFun(ThisFun)
      end
spawn(fun() -> Fun(Fun) end),
%% ...

【讨论】:

    【解决方案2】:

    如果你想稍微扭曲一下:

    Y = fun(M,B) -> G = fun(F) -> M(fun() -> (F(F))() end, B) end, G(G) end.
    spawn(Y(fun(F, ParentPid) -> fun() -> ParentPid ! wake_up, receive after 1000 -> ok end, F() end end, self())).
    

    刷新消息几次以查看结果:

    flush().
    

    当然,如果将 Y 放在某种库中,它会更有用。 你也可以在 Y Combinators 上找到这篇文章:http://bc.tech.coop/blog/070611.html 很有趣

    【讨论】:

      【解决方案3】:

      Erlang 语言没有公开任何匿名函数引用它们的方式,但有传言称 Core Erlang(编译器阶段的中间但官方表示)确实具有这样的功能。

      我不知道我为什么要转发这个,但你知道,如果你碰巧在 DSL 或类似文件中生成 Core Erlang,那是触手可及的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-13
        • 1970-01-01
        • 2011-08-11
        • 1970-01-01
        • 2016-04-11
        • 1970-01-01
        相关资源
        最近更新 更多