Erlang 是否支持 "ask" 操作?

Does Erlang support an "ask" operation?

在 Akka 中你有两种不同的发送机制:! 用于 告诉 演员的东西,? 用于 询问 一个关于东西的演员,对于那些不熟悉的人来说,主要区别在于 actor ! message 是一个 即发即弃 操作,而 actor ? message returns 对结果的承诺,稍后需要解决。

我无法在 Erlang 中找到与此相关的任何信息,因为谷歌搜索 "Erlang ask operation" 或简单地 "Erlang ask" 产生的结果不太有用。

不,不是,但是你的要求很容易实现:

ask(Pid, M) ->
  Promise = erlang:monitor(process, Pid),
  Pid ! {ask, Promise, M},
  Promise.

现在可以通过以下方式等待承诺的结果:

force(Promise, Timeout) ->
  receive
    {result, Promise, R} ->
      erlang:demonitor(Promise, [flush]),
      {ok, R};
    {'DOWN', Promise, process, _, Reason} ->
      {error, {callee_died, Reason}}
  after Timeout -> {error, timeout}
  end.

如果您不想在请求和强制之间做任何事情,那么您可以使用 OTP 行为 gen_server,它具有 gen_server:call/3 本质上一次性实现这两个功能。

请注意,在上面我们如何在目标 Pid 上请求监视器引用,这允许我们在它死亡时对其进行监视。我们还将此引用用作承诺的唯一标记,以便我们可以在邮箱中的其他消息中找到它。

Erlang 不支持 promises 和 futures。请参阅 this question for other examples of simulating them. Also see this article 了解为什么 Erlang 使用消息传递而不是 Promises 和 Futures 的解释。

Akka 中的 ? 是使用 ! 构建的。它的作用是:它创建一个新的临时角色,用作使用普通 ! 发送的消息的 sender。如果它没有及时收到任何东西,它会将承诺设置为失败。做到了就兑现承诺了。

然后被询问的演员将回复那个临时演员(这是您知道实际回复了哪条消息的方式,否则您必须自己在地图或类似的东西中跟踪它)。

这就是为什么您必须显式导入 ask 模式以及为什么它被称为模式,而不是像 ! 那样的内置基元。

您可以在 Erlang 中实现相同的模式。