When running this module:
-module(cbbs).
-export([ahu/0, duct/1, simulate/0, room1/1, vent1/0]).
duct(P) ->
if
P>=250 ->
apid ! full,
io:format("Full Pressure~n", []),
receive
gia ->
vent1 ! {gia, self()},
io:format("Feeding Vent1~n", []),
duct(P-2)
end;
true ->
apid ! {pressurise, self()},
receive
pressurise ->
io:format("Receiving Pressure~n", []),
duct(P + 1);
gia ->
vent1 ! gia,
io:format("Feeding Vent1~n", []),
duct(P - 1)
end
end.
ahu() ->
receive
full ->
io:format("Stopped~n", []);
{pressurise, duct} ->
io:format("Pressurising~n", []),
duct ! pressurise,
ahu()
end.
vent1() ->
receive
{toohot, room1} ->
io:format("Open~n", []),
duct ! gia;
{roomtemp, room1} ->
io:format("Closed~n", []);
{gia, duct} ->
io:format("Feeding Room1~n", []),
room1 ! ga,
vent1()
end.
room1(T) ->
if
T >= 20 ->
vent1 ! {toohot, self()},
io:format("R1 Too Hot~n", []),
receive
ga ->
io:format("Cooling R1~n", []),
room1(T-1)
end;
true ->
vent1 ! {roomtemp, self()},
io:format("Room Temperature~n", []),
room1(T+1)
end.
simulate() ->
register(apid, spawn(cbbs, ahu, [])),
register(vent1, spawn(cbbs, vent1, [])),
register(duct, spawn(cbbs, duct,[0])),
register(room1, spawn(ccbs, room1, [20])).
I get this error:
cbbs:simulate().
** exception error: bad argument
in function register/2
called as register(apid,<0.292.0>)
in call from cbbs:simulate/0 (cbbs.erl, line 76)
I can't seem to understand any further what it is asking of me. This is meant to simulate a concurrent building services and making this somewhat complicated in terms of communication. I can't however, find out what the problem is here, and therefore can't move on to finding what other problems there are !
Any help would be greatly appreciated !
EDIT:
I get the following from running first time:
=ERROR REPORT==== 10-May-2017::15:36:54 ===
Error in process <0.69.0> with exit value:
{undef,[{ccbs,room1,[20],[]}]}
Followed by the error previously mentioned.
2条答案
按热度按时间a9wyjsp71#
您在
simulate()
的最后一行拼错了模块名称cbbs
:第一次运行程序时,会在该行中出现错误。第二次运行程序时,会在
simulate()
的第一行中出现错误:这是因为在第一次运行程序时,注册的进程会陷入无限循环,因此在程序结束后,它们将永远存在于shell中。(重新编译不会有帮助)。由于程序中的问题,为了第二次运行程序,你需要杀死erlang shell并启动一个新的erlang shell。2这将终止你第一次运行程序时遗留下来的进程。
试试这个:
1.更正拼写错误。
1.启动新的Erlang shell。
1.运行
simulate()
。1.在shell中使用
i()
命令检查当前正在运行的进程。下面是一个例子:
在
i()
输出中,第一列的标题为:该列列出了当前在shell中运行的进程的所有 * 进程标识符 *(Pid)以及Pid下的进程的注册名称--如果该进程已注册的话。您可以看到已注册的进程列在第一列的底部。您的程序已终止,但那些进程仍在shell中运行。
在
i()
输出中,第二列的标题为:Initial Call
是您调用以启动进程的函数,例如spawn(ccbs, room1, [20])
,在它下面是该进程中当前正在执行的函数。例如,如果room1()
调用帮助函数来执行循环,例如loop()
,则在第二列中您将看到:流程陷入无限循环的原因是因为receive子句中的模式有错误。例如,当您在这里发送消息时:
self()
不返回room1
,因此在此处的receive子句中:模式
{toohot, room1}
将与room1()
发送的消息不匹配。self()
实际上返回一个Pid--不是注册名称。转换为字符串以供输出的Pid如下所示:<0.66.0>
(但请记住,Pid不是字符串,因此不能在Pid的代码中编写"<0.66.0>"
)。您需要更改receive子句中的模式。您可以将模式更改为:
该接收模式将匹配第二项为 * anything * 的元组。或者,您可以将接收模式更改为:
whereis()
返回注册名称的Pid。在这种情况下,接收模式将只匹配第二个元素是room1
进程的Pid的元组。另外,
if-statements
在Erlang中也不受欢迎。请查看以下room1()
的替代方法:函数子句的匹配顺序与它们在代码中的写入顺序相同。因此,当你调用
room1()
时,第一个Erlang将尝试匹配函数子句:如果
T
小于20,则该函数子句将不匹配,因此Erlang将继续执行下一个函数子句:该函数子句将匹配任何单个参数,因此它将执行。请注意,函数子句之间用分号而不是句点分隔。如果不小心使用了句点,将出现以下错误:
功能室1/1已定义
如果你觉得先写一个
if-statement
是很自然的,那就继续写吧......但要马上把if-statement
转换成一系列的function clauses
。在你做了一段时间的转换之后,我想你的头脑会适应用function clauses
而不是if-statements
来思考。而且,我看到你在做我以前做的同样的事情:
io:format()
还有一个额外的单参数形式,所以你可以写:这对于打字来说不那么痛苦。
2nc8po8w2#
如果名称已经忙或者进程在你注册它之前就已经死了,register调用可能会失败。你可以用whereis(ProcessName)检查第一种情况,用erlang:is_process_alive(Pid)检查第二种情况。