如何向Erlang中的进程列表广播消息?控制台悬挂
我是Erlang的新手,我试图了解如何将消息从一个进程发送到一个进程列表 假设我们有一个数据结构,其中包含一个包含字符串和Pid的元素的列表。如何使Pid向前面描述的两个元素之一的Pid发送消息“M”? 我想到的是:如何向Erlang中的进程列表广播消息?控制台悬挂,erlang,erlang-shell,Erlang,Erlang Shell,我是Erlang的新手,我试图了解如何将消息从一个进程发送到一个进程列表 假设我们有一个数据结构,其中包含一个包含字符串和Pid的元素的列表。如何使Pid向前面描述的两个元素之一的Pid发送消息“M”? 我想到的是: broadcast(P, M, R) -> P ! {self(), friends}, receive {P, Friends} -> P ! {self(), {send_message, {M, R, P, Friends}}} end.
broadcast(P, M, R) ->
P ! {self(), friends},
receive
{P, Friends} ->
P ! {self(), {send_message, {M, R, P, Friends}}}
end.
looper({Name, Friends, Messages}) ->
receive
{From, friends} ->
From ! {self(), Friends},
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.
其中“M”是我想要广播到称为“Friends”的PID列表的消息,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、设置Pid之间的“友谊”并广播消息后,我从终端获得的信息是:
1> f().
ok
2> c(facein).
facein.erl:72: Warning: variable 'From' is unused
{ok,facein}
3> {Message, Pid} = facein:start({"dummy", [], []}).
{ok,<0.186.0>}
4> {Message, Pid2} = facein:start({"dummy2", [], []}).
{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>}}}
1>f()。
好啊
2> c(面内)。
facein.erl:72:警告:变量“From”未使用
{好的,facein}
3> {Message,Pid}=facein:start({“dummy”,[],[]})。
{好的,}
4> {Message,Pid2}=facein:start({“dummy2”,[],[]})。
{好的,}
5> facein:添加朋友(Pid,Pid2)。
好啊
6> facein:广播(Pid,“你好”,1)。
=错误报告===2014年10月5日::12:12:58===
使用退出值进行处理时出错:{if_子句,[{facein,looper,1,[{file,“facein.erl”},{line,74}]}
{,{发送消息,{“你好”,1,{Ref}}
当我查看广播消息的Pid的消息时,控制台只是挂起,其他Pid没有收到消息
任何帮助都将不胜感激。
谢谢错误消息
这一次您得到的是if_子句
错误。在Erlang中,如果包含,则每个表达式都必须返回一些值。这意味着您可以编写这样的代码
SomeVar = if
R =< 0 ->
[...]
R > 0 andalso FriendTale =/= []->
[...]
end
这将始终匹配,并使您免于此类错误
在您的示例中,如果
,则根本不必使用。你所能做的就是用一些警卫延长你收到的条款
looper({Name, Friends, Messages}) ->
receive
{From, {send_message, {M, R, ID, [{FriendPid, FriendName} | FriendTale]}}}
when R =< 0 ->
From ! {From, {self(), {ID, M}}},
looper({Name, [{FriendPid, FriendName} | FriendTale], [{ID, M} | Messages]});
{From, {send_message, {M, R, ID, [{FriendPid, FriendName} | FriendTale]}}}
when R > 0 andalso FriendTale =/= [] ->
FriendPid ! {From, {send_message, {M, R-1, ID, FriendTale}}},
looper({Name, FriendTale, [{ID, M} | Messages]});
terminate ->
ok
end.
为了增加可读性,您可以将R
从opque integer更改为miningfull原子
looper({Name, Friends, Messages}) ->
receive
{From, {send_message, {M, back_to_me, ID, [{FriendPid, FriendName} | FriendTale]}}} ->
From ! {From, {self(), {ID, M}}},
looper({Name, [{FriendPid, FriendName} | FriendTale], [{ID, M} | Messages]});
{From, {send_message, {M, to_friends, ID, [{FriendPid, FriendName} | FriendTale]}}}
when FriendTale =/= [] ->
FriendPid ! {From, {send_message, {M, R-1, ID, FriendTale}}},
looper({Name, FriendTale, [{ID, M} | Messages]});
terminate ->
ok
end.
向朋友广播
如果我理解正确的话,looper
是表示一个“人”的函数。每个好友都是一个进程,它存储好友列表,可以在其中添加和删除好友,还可以向其他好友发送消息
让我们从为每个函数创建子句开始(创建流程接口)
其中大多数都很容易实现,比如
{add_frined, Friend} ->
looper(Name, [Friend, Friends], Messages);
因此,我不会详细说明
做广播的不会改变状态,所以现在让我们写一些类似的东西(主要是为了可读性)
{broadcast_to_friends, Message} ->
handle_broadcast_to_friends(Friends, Message),
looper(Name, Friends, Messages);
并实现下面的新功能
handle_broadcast_to_friends(Friends, Message) ->
[ F ! {receive_message, Message} || F <- Friends ].
我们也可以在逻辑实现中使用它们
handle_broadcast_to_friends(Friends, Message) ->
[ receive_message(F, Message) || F <- Friends ].
handle\u broadcast\u\u\u to\u friends(朋友,消息)->
[接收信息(F,信息)| | F我建议您先将所做工作的复杂性降低到基本内容。例如,接收中的条件处理业务不是基本消息传递问题的一部分。下面是一个常见广播习惯用法的基本示例,使用列表理解发送到函数bcast/2 :
-module(bcast).
-export([start/0]).
start() ->
Pids = [spawn(fun() -> listener() end) || _ <- lists:seq(1,3)],
Message = "This is my message.",
ok = bcast(Pids, Message),
timer:sleep(100), % Give the subordinates time to act.
[exit(P, kill) || P <- Pids],
ok.
listener() ->
receive
{bcast, Message} ->
Now = now(),
io:format(user, "~p ~p: Received: ~p~n", [self(), now(), Message]),
listener();
Any ->
io:format(user, "~p HURR! Unexpected message: ~p~n", [self(), Any]),
listener()
end.
bcast(Pids, Message) ->
[P ! {bcast, Message} || P <- Pids],
ok.
-模块(bcast)。
-导出([start/0])。
开始()->
Pids=[spawn(fun()->listener()end)| |
Now=Now(),
io:格式(用户,“~p~p:Received:~p~n”,[self(),now(),Message]),
监听器();
任何->
io:格式(用户,“~p HURR!意外消息:~p~n”,[self(),Any]),
监听器()
结束。
bcast(Pids,消息)->
[P!{bcast,Message}| | P此处不够详细,循环器函数甚至不是有效的erlang(缺少接收)。我在循环器中添加了接收(我的坏)。您还需要什么其他信息?也许我可以告诉您,但是我的语法是否正确,可以尝试将消息传递到进程列表?我在接收块中添加了另一个模式,因为再次看到错误报告,它提到的第74行是这一行:From!{self(),Friends},
{broadcast_to_friends, Message} ->
handle_broadcast_to_friends(Friends, Message),
looper(Name, Friends, Messages);
handle_broadcast_to_friends(Friends, Message) ->
[ F ! {receive_message, Message} || F <- Friends ].
add_friend(Person, Friend) ->
Person ! {add_friend, Friends}.
receive_message(Person, Message) ->
Person ! {receive_message, Message}.
handle_broadcast_to_friends(Friends, Message) ->
[ receive_message(F, Message) || F <- Friends ].
-module(bcast).
-export([start/0]).
start() ->
Pids = [spawn(fun() -> listener() end) || _ <- lists:seq(1,3)],
Message = "This is my message.",
ok = bcast(Pids, Message),
timer:sleep(100), % Give the subordinates time to act.
[exit(P, kill) || P <- Pids],
ok.
listener() ->
receive
{bcast, Message} ->
Now = now(),
io:format(user, "~p ~p: Received: ~p~n", [self(), now(), Message]),
listener();
Any ->
io:format(user, "~p HURR! Unexpected message: ~p~n", [self(), Any]),
listener()
end.
bcast(Pids, Message) ->
[P ! {bcast, Message} || P <- Pids],
ok.