【问题标题】:Erlang console hangs with this codesnippetErlang 控制台挂起这个代码片段
【发布时间】:2012-11-07 20:09:31
【问题描述】:

这对于有 Erlang 经验的人来说可能很容易,但我没有。 我试图制作一个斐波那契进程树。然后它应该接受一条消息,我可以在其中计算传递给它的那个节点下所有节点的总和。

create_fibtree(N) when N > 1 ->
Child1 = spawn(fun() -> create_fibtree(N-1) end),
Child2 = spawn(fun() -> create_fibtree(N-2) end),

receive 
    Sum ->
        Child1 ! sum + 1,
        Child2 ! sum + 1,
        io:format ("sum is ~p.~n", [Sum])
end;
create_fibtree(N) when N =< 1 ->
    ok.

当我运行这个时:

c(fib_tree2).
{ok,fib_tree2}
2> fib_tree2:create_fibtree(10).

Erlang 控制台挂起。不知道为什么,但它与接收子句有关吗?

是的,这是作业,我的老师这周不在,这就是我在互联网上寻找替身的原因。

【问题讨论】:

  • 嗯,我通常会在电子邮件中回复,通常在收到电子邮件后不到一个小时...!埃米尔的答案是正确的。但是,我不确定 stackoverflow 对家庭作业问题的政策。
  • aronisstav, How to ask and answer homework questions? 只要问题是主题,我们就应该尝试回答它,imo。请注意,我在回答中试图避免任何会造成作弊情况的事情。

标签: concurrency erlang message-passing erlang-shell


【解决方案1】:

没错,receive 子句阻塞了函数,因为它从不接收任何消息。 但一般来说,这段代码并不是计算 fib 数的好方法。 它可以通过一个简单的递归函数来完成,而不需要产生进程。

附: 孩子 1 ! sum + 1,将失败,因为您尝试添加原子和整数

【讨论】:

  • 但是它不应该在收到消息之前等待接收子句吗?仍然不明白它为什么会挂起。我生成过程导致它在练习中这么说。
  • 它等待消息,但是当您在主进程(即从 shell)中运行该函数时,它会阻塞它,请尝试以下操作: Pid = spawn(module,create_fibtree, [10]),皮德! 10.
【解决方案2】:

您需要有第一条消息。因为我也有the assignment,所以我可以提供一些提示:

  • 尝试将树的创建与总和计算分开。创建树,然后移动到您接收和发送消息的另一个函数。

  • 必须有人发送消息才能收到消息。

  • 您似乎对消息传递的方向感到困惑。您可能应该在树中向下发送一条消息(告诉您的孩子您正在计算节点),然后在树中向上发送一条消息(来自每个节点的结果)。以下是对算法的建议:

在每个节点中:

  1. 向两个孩子发送消息 {get_sum, Id, Pid},其中 Id 是一些随机的唯一标识符,例如,来自 now/0 函数,Pid 来自 self/0
  2. {sum, Id, Sum} 表格上恰好收到两个答案(每个孩子一个)(其中Id 与以前相同)。
  3. 两个总和相加,您为当前节点加 1。
  4. 将答案发送回树中的父级。

查看Erlang debugger,它非常适合解决此类问题:

> c(modulename, [debug_info]).
> debugger:start().
(Module -> Interpret -> Pick the .erl file for the module you just compiled)

【讨论】:

  • 感谢您的提示,非常感谢。尼斯也有一些其他人的意见,他们做了同样的练习。我最终在没有您建议的 ID 的情况下使用了一些消息传递来传递总和。将看看 Erlang 调试器,似乎是一个不错的工具。
  • 另一个有趣的方面是如何使用通用服务器解决这个问题。我尝试过但没能完成的事情
猜你喜欢
  • 2014-04-22
  • 2012-10-18
  • 1970-01-01
  • 2021-06-04
  • 2010-12-14
  • 1970-01-01
  • 2013-03-12
  • 1970-01-01
  • 2012-01-16
相关资源
最近更新 更多