我是Erlang的新手,我正在尝试了解如何将消息从一个进程发送到进程列表。
据说我们有一个数据结构,其中包含一个带有Pids的列表。如何让Pid发送消息" M"到Pids列表,其中列表的每个元素都有2个元素:一个字符串(代表一个名字)和Pid? 我想出的是:
broadcast(P, M, R) ->
P ! {self(), friends},
receive
{P, Friends} ->
P ! {self(), {send_message, {M, R, P, Friends}}}
end.
looper({Name, Friends, Messages}) ->
{From, {send_message, {M, R, ID, [{FriendPid, FriendName} | FriendTale]}}} ->
if R =< 0 ->
From ! {From, {self(), {ID, M}}},
looper({Name, [{FriendPid, FriendName} | FriendTale], [{ID, M} | Messages]});
R > 0 andalso FriendTale =/= []->
FriendPid ! {From, {send_message, {M, R-1, ID, FriendTale}}},
looper({Name, FriendTale, [{ID, M} | Messages]})
end;
terminate ->
ok
end.
但据我所知,我并没有正确匹配Pids列表,因此我可以提取&#34;来自Pids列表元素的Pid。
基本上,我有一个名为&#34; looper&#34;这是不断等待新消息到来。当它收到类型
的消息时{send_message, {M, R, ID, [{FriendPid, FriendName} | FriendTale]}}
其中&#34; M&#34;是我想要广播到名为&#34; Friends&#34;的Pids列表的消息。和R只是一个整数。
R基本上是一个整数,表示消息应该走多远。
e.g. 0 = broadcast the message to self,
1 = broadcast the message to the friends of the pid,
2 = broadcast the message to the friends of the friends of the pid and so on...
在我设置Pid并设置&#34;友谊&#34;之后我从终端获得了什么? Pids之间是:
1> f().
ok
2> c(facein).
facein.erl:72: Warning: variable 'From' is unused
{ok,facein}
3> {Message, Pid} = facein:start({"Bjarki", [], []}).
{ok,<0.186.0>}
4> {Message, Pid2} = facein:start({"Bjarki2", [], []}).
{ok,<0.188.0>}
5> facein:add_friend(Pid,Pid2).
ok
6> facein:broadcast(Pid,"hello",1).
=ERROR REPORT==== 5-Oct-2014::12:12:58 ===
Error in process <0.186.0> with exit value: {if_clause,[{facein,looper,1,[{file,"facein.erl"},{line,74}]}]}
{<0.177.0>,{send_message,{"hello",1,#Ref<0.0.0.914>}}}
非常感谢任何帮助。 感谢
答案 0 :(得分:1)
修改强>
添加brodcast功能后。您收到的发送给looper
函数的内容是friends
atom。你不能在原子上做列表理解,只能在列表上。这就是您尝试使用bedarg
运算符时获得<-
的原因。
打破你的逻辑:你把你的pid和atom发送给自己,只是为了以后收到一行。不知道为什么你需要这样做?你可以直截了当地说:
broadcast(P, M, R) ->
P ! {self(), {send_message, {M, R, P, friends}}}.
现在你可以清楚地看到,你发送给looper
是原子,而不是pid列表。
错误您建议您使用错误类型调用某些内置Erlang函数(+
!
)。所以我猜想Friends
中的一个不是一个过程,或者R
不是- 1
。也许在列表理解之前尝试将它们打印出来进行调试。
你也可以使用像
这样的守卫receive
{From, {send_message, {M, R, ID, Friends}}} when is_integer(R) ->
%% ...
但您只会忽略不匹配模式的邮件。
我不确定这是不是你想做什么,但那些也可能有帮助。
我可以注意到的一件事是你发送元组的事实
{send_message, {M, R-1, ID, Friends}}
。那是你的全部信息,只有这一点才会收到。 Erlang将不神奇地添加任何内容,因此如果您指望接收{From, {send_message, {M, R, ID, Friends}}}
,则需要自己发送此From
。像这样F ! {self(), {send_message, {M, R-1, ID, Friends}}}
您可能关注的其他事情是“更长”功能中的模式匹配。 Friends
变量被绑定(赋值)作为函数参数。所以当你正在做receive {From, {send_message, {M, R, ID, Friends}}}
你正在做的事情时,是消息类型上的模式匹配(两元组,带有四元组的二元组),原子send_message
和 Friends
列表。这意味着只有当您收到与最初调用loop
函数完全相同的朋友列表时,才会执行“发送逻辑”。所有其他消息(当然除了terminate
)都将被忽略(只会留在您的消息框中)。如果你指望接收一些新朋友,对未绑定变量的模式匹配(保持函数简短有助于这个Erlang-gotcha)。