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

发布于 2024-07-28 16:42:41 字数 625 浏览 4 评论 0原文

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

In Erlang is there a way reference the currently executing function)?

That would be useful to spawn an infinite loop:

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

In JavaScript arguments.callee does just that, see the specification on MDC.

Edit to answer a 'why would you do that': mostly curiosity; it is also useful to define a timer when prorotyping:

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

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

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

发布评论

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

评论(3

贪恋 2024-08-04 16:42:59

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

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

The Erlang language does not expose any way for anonymous functions to refer to them self, but there is a rumour that Core Erlang (an intermediate but official representation in the compiler phases) does have such a feature.

I don't know why I am forwarding this, but you know, if you happen to be generating Core Erlang in a DSL or similar it is something that is within reach.

笑叹一世浮沉 2024-08-04 16:42:54

如果您想稍微扭转一下情况:

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 上找到 这篇文章组合器很有趣

If you feel like twisting things a little bit:

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 the messages couple times to see the result:

flush().

Of course, Y is more useful if you put it in some sort of library.
Also you can find this post on Y Combinators quite interesting

一杯敬自由 2024-08-04 16:42:51

在 Erlang/OTP 17.0 及更高版本中,您可以使用命名的 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),
%% ...

In Erlang/OTP 17.0 and later, you can use a named fun for that:

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

In earlier versions, there is no way to do exactly that. You could pass the function itself as an argument:

Self = self(),
Fun = fun(ThisFun) ->
          Self ! wake_up,
          receive after 1000 -> nil end,
          ThisFun(ThisFun)
      end
spawn(fun() -> Fun(Fun) end),
%% ...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文