让我们看一下前两行。
-module(pingpong).
-compile(export_all).
第一个是模块声明,它的参数是一个原子(或者,换句话说,一个小写单词,不带引号)。取自Learn You Some Erlang:
-module(Name).
这始终是文件的第一个属性(和语句),并且有充分的理由:它是当前模块的名称,其中 Name 是一个原子。这是您将用于从其他模块调用函数的名称。调用是使用M:F(A)
表单进行的,其中M
是模块名称、F
函数和A
参数。
第二句告诉您的编译器将所有声明的函数公开,即您在该模块上编写的每个函数F
都可以被外部人员调用为pingpong:F
.
当您第一次学习时,这可能会简化流程,但这通常是一种不好的做法。参考这个问题。
现在让我们看一下这些功能。
start_pong() ->
register(pong, spawn(pingpong,pong,[])).
这可能是您的代码开始的地方。您编译模块,然后调用pingpong:start_pong().
给定机器或节点的 Erlang shell。这个函数所做的只是“将名称pong注册为我将要创建的进程的标识符,使用spawn
”。
因此,spawn
创建了一个 Erlang 进程。spawn
也是一个内置函数 (BIF),因此不需要您在其模块名称前添加。如文档spawn(Module, Exported_Function, List of Arguments)
中所见,它的论点是。
回顾一下,它所做的只是“创建一个进程,该进程将通过运行此模块中的函数开始,不带参数,并调用该进程pong ”。
start_pong
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
,否则忽略此语句。
如果进程有一条带有单个 atom 的消息,它会在控制台中finished
打印并退出。
如果进程有一条消息,它是与原子和进程标识符(pid - 每个进程都有一个)成对的消息,那么它将执行函数的剩余代码。Pong finished
ping
大写字母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
响应,并再次重复此操作,whileN
大于零。
当N
达到零时,第一个案例被执行,发送finished
到{pong, Pong_Node}
,并结束执行。
如果你觉得这个解释不完整,你也可以看看教程,它描述了这个确切的程序。