Erlang:如何在体内引用匿名函数?

时间:2009-07-24 19:25:21

标签: erlang

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),
%% ...

3 个答案:

答案 0 :(得分:27)

在Erlang / OTP 17.0-rc1中,您可以使用命名的乐趣:

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),
%% ...

答案 1 :(得分:7)

如果你想稍微扭转一下事情:

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非常有趣

答案 2 :(得分:3)

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

我不知道为什么要转发这个,但是你知道,如果你碰巧在DSL或类似产品中生成Core Erlang,那么它就是可以实现的。