这个代码是我们老师给我们的,但遗憾的是,没有得到解释。我们刚在课堂上试过这个,后来被开除了。
如果有人能彻底地向我解释这段代码,那将是非常有帮助的。提前谢谢。
-module(pingpong).
-compile(export_all).
start_pong() ->
register(pong, spawn(pingpong,pong,[])).
pong() ->
receive
finished ->
io:format("Pong finished ~n");
{ping, Ping_Pid} ->
io:format("i am the receiver ~n"),
Ping_Pid ! pong,
pong()
end.
start_ping(Pong_Node) ->
spawn(pingpong, ping, [3, Pong_Node]).
ping(0, Pong_Node) ->
{pong, Pong_Node} ! finished,
io:format("Pong finished ~n");
ping(N, Pong_Node) ->
{pong, Pong_Node} ! {ping, self()},
receive
pong ->
io:format("i am the sender ~n")
end,
ping(N-1,Pong_Node).发布于 2013-09-29 09:52:22
让我们看看前两行。
-module(pingpong).
-compile(export_all).第一个是模块声明,它的参数是一个原子(换句话说,是一个小写单词,没有引号)。从你身上学到一些二郎
-module(Name).这始终是文件的第一个属性(和语句),并且有充分的理由:它是当前模块的名称,其中name是一个原子。这是您将用于从其他模块调用函数的名称。调用使用M:F(A)表单进行,其中M是模块名,F是函数,A是参数。
第二句命令编译器将所有声明的函数公之于众,也就是说,您在该模块上编写的每个函数F都可以被外部调用为pingpong:F。
当你第一次学习的时候,这可能会简化你的学习过程,但这通常是一种糟糕的做法。请参阅这个问题。
现在让我们来看看这些函数。
start_pong() ->
register(pong, spawn(pingpong,pong,[])).这可能是您的代码开始的地方。编译模块,然后在给定机器或节点的Erlang中调用pingpong:start_pong().。这个函数所做的就是“注册名称pong作为我将要创建的进程的标识符,使用spawn__”。
因此,spawn创建了一个Erlang进程。spawn也是一个内置函数(BIF),因此不需要在它的模块名之前加上它。它的论点是spawn(Module, Exported_Function, List of Arguments),如在文件中所见。
回顾一下start_pong,它所做的就是“创建一个进程,在这个模块中运行不带参数的pong函数,并调用process pong__”。
pong() ->
receive
finished ->
io:format("Pong finished ~n");
{ping, Ping_Pid} ->
io:format("i am the receiver ~n"),
Ping_Pid ! pong,
pong()
end.start_pong中新创建的进程将运行此函数。Erlang中的每个进程都有自己的邮箱。进程通过在这些邮箱中留下邮件来相互通信。信息可能几乎是任何东西。将它们看作是您喜欢在进程之间发送的一些数据。
新进程进入receive语句,该语句告诉它从其邮箱中获取一条消息,或者等到有一些消息。然后,当接收到消息时,它使用模式匹配来查找适当的操作。如果您习惯于命令式语言,请将其视为一个switch,否则忽略此语句。
如果进程有一个带有单个原子finished的消息,它会在控制台中打印Pong finished并退出。
如果进程有一个带有原子ping的消息和一个进程标识符 (pid -每个进程都有一个),那么它将执行函数的其余代码。
大写的Ping_Pid告诉Erlang将消息的第二个值分配给名为Ping_Pid的变量。只是碰巧你期望得到pid。
在这种情况下,它所做的是打印i am the receiver,然后用原子pong向Ping_Pid标识的进程发送一条消息--这就是!操作符的作用。最后,函数调用自己,以便再次查看邮箱。
接下来您将在控制台上(可能是在另一个节点/机器上)编写对start_ping的调用。
start_ping(Pong_Node) ->
spawn(pingpong, ping, [3, Pong_Node]).正如我们前面看到的,所有这些都是创建一个将运行ping函数的进程,其中包含参数3及其接收的Pong_Node,这是第一个进程正在运行的机器(节点)。
ping(0, Pong_Node) ->
{pong, Pong_Node} ! finished,
io:format("Pong finished ~n");
ping(N, Pong_Node) ->
{pong, Pong_Node} ! {ping, self()},
receive
pong ->
io:format("i am the sender ~n")
end,
ping(N-1,Pong_Node).这个函数是在两种情况下定义的(注意,第一个ping块以;结束,而不是. -这告诉Erlang还有更多的函数需要定义)。
您可以使用3作为第一个参数来调用它。由于3与0不匹配,所以进程执行第二种情况,以N作为参数。
此过程将对{ping, self()}发送到{pong, Pong_Node}给出的进程,该进程遵循语法{registered_name, node_name}。self()用于检索当前进程自己的pid。
在此之后,进程等待pong响应,并再次重复该响应,而N大于零。
当N达到零时,将执行第一个情况,将finished发送到{pong, Pong_Node},并结束执行。
如果你觉得这个解释是不完整的,你也可以看看在教程中,它描述了这个精确的程序。
https://stackoverflow.com/questions/19075965
复制相似问题