长话短说我试图在Erlang中复制睡眠理发师问题。
在我的解决方案中,我决定对于所有等待的进程,我会将它们放入列表中。然后,一旦进程转过来,我就会把PID从列表中删除。
不幸的是,当我打电话
length(myListOfPids).
它失败了,例如:
length([<0.46.0>]).
* 2: syntax error before: '<'
有没有办法存储PID,以便我可以调用它们并正常使用它们?即。
PID ! message
...以防这里重要的是我在运行程序时收到的实际错误:
=ERROR REPORT==== 1-Jul-2010::05:50:40 ===
Error in process <0.44.0> with exit value:
{badarg,[{erlang,length,[<0.46.0>]},{barber1,waitingRoom,2}]}
barber1是我的模块,waitingRoom是跟踪哪些进程正在等待的函数
答案 0 :(得分:10)
你也可以使用pid / 3从它的三个组件构建一个Pid。
1&GT;长度([PID(0,35,0)])。
请注意,如果您在与创建Pid的节点不同的节点上构建pid,则使用这些技术构建Pid会出错。
你的程序遇到的问题是不同的。
{badarg,[{二郎,长度,并[d 0.46.0&GT;]},{barber1,候车室,2}]}
对erlang的调用:length / 1创建了一个badarg。 {erlang,length,[&lt; 0.46.0&gt;]}的第三个元素是传递给erlang:length的参数列表。所以这相当于:
1&GT;二郎:长度(PID(0,46,0))
你想要的地方:
1&GT;二郎:长度([PID(0,46,0)])
(令人讨厌的是,erlang shell现在隐藏了erlang对你的错误的内部表示。用以下代码替换上面的错误:
**异常错误:函数长度/ 1中的错误参数称为长度(&lt; 0.35.0&gt;)
这更容易理解但不太有用,因为它妨碍了自己学习解释erlang错误的基本技能。)
答案 1 :(得分:6)
通过输入Pids输入Pids对我来说也不起作用。 这是唯一的问题吗?
使用代码:
-module(test).
-export([loop/0]).
loop() ->
receive
{hello} ->
io:format("Hello world!~n"),
loop()
end.
我明白了:
Eshell V5.7.5 (abort with ^G)
1> Pid = spawn(fun test:loop/0).
<0.35.0>
2> L = [Pid].
[<0.35.0>]
3> length(L).
1
答案 2 :(得分:5)
此错误消息:
=ERROR REPORT==== 1-Jul-2010::05:50:40 ===
Error in process <0.44.0> with exit value:
{badarg,[{erlang,length,[<0.46.0>]},{barber1,waitingRoom,2}]}
表示您正在调用length(<0.46.0>)
,而不是 length([<0.46.0>])
(忽略PID只能写入,而不能读取)。在堆栈跟踪中,最顶层的函数将具有参数的列表。由于length
接受一个参数,因此该列表只有一个参数:您正在获取PID的长度,这显然会失败,因为只有列表具有长度。
答案 3 :(得分:3)
问题是虽然<0.46.0>
是PID 打印的方式,但它不能以这种方式输入。您可以改用list_to_pid("<0.46.0>")
。当然,一旦你有了PID(以这种方式创建,从spawn
返回等),它就可以存储在列表中并像任何其他Erlang术语一样被检索。
答案 4 :(得分:2)
获取pid的标准方法是获取生成函数的返回值,spawn/1
,spawn/3
,spawn_link/1
,spawn_link/3
和{{ 1}}等价物。
记下pid的一种简单方法是使用函数c:pid / 3,称为proc_lib
,它将返回c:pid(0,25,0)
。这是shell的快捷功能。否则,您可以使用Alexey Romanov提到的<0.25.0>
。
但是,在尝试手动构建pid之前,您应该了解pid的作用。 pid充当进程的个人标识符,并且仅供了解它的人使用。如果你手上还没有pid,那么你可能不应该拥有它。间接地,这意味着导致程序的不同部分的绝缘 - 只关心您产生的那些部分,并让程序的每个部分都关注自己的业务。
最简单的方法是使用spawn函数的返回值。 手动生成pid只能作为调试解决方案。