我正在尝试制作 Erlang 程序,它通过过程找到质数(我知道无效,但嘿,这只是为了好玩:)) - 类似于 numbersimulation.com 的东西。
在每个"滴答"上,服务器都会生成新的进程("数字"),从而增加其计数器。如果计数器==这个数字,这是一个因素,所以我们让服务器知道。如果服务器没有收到任何消息,则它是质数。
在小数字(素数到 N 之前,server(50,L)
行)上没关系,但在较大的数字上,它会崩溃:
Error in process <0.46.0> with exit value: {badarg,[{primes,number,2,[{file,"primes.erl"},{line,31}]}]}
第 31 行是server ! hit
行 - 但我不明白为什么它会失败。也许失败的那条线是后面的那条,number(N,1)
?但为什么会失败呢?
代码:
-module(primes).
-compile(export_all).
main() ->
pg:create(numbers),
Server_PID = spawn(?MODULE,server,[]),
register(server,Server_PID),
ok.
server() -> server(2,[]).
server(50,L) -> io:format("Primes: ~p~n",[L]);
server(N,L) ->
Num_PID = spawn(?MODULE,number,[N]),
pg:join(numbers,Num_PID),
pg:send(numbers,tick),
receive
hit ->
flush(),
server(N+1,L)
after 100 ->
server(N+1,[N|L])
end.
number(N) -> receive {pg_message,_,_,tick} -> number(N,1) end.
number(N,I) ->
receive
{pg_message,_,_,tick} ->
if
N =:= I ->
server ! hit,
number(N,1);
true ->
number(N,I+1)
end
end.
flush() ->
receive _ -> flush()
after 0 -> ok end.
当已注册的进程死亡时,注册该进程的名称将不再注册。虽然向引用死进程的 pid 发送消息是完全合法的(消息只是消失),但发送到未注册的名称是一个错误,即使该名称曾经注册过。
在代码中,server
进程执行 50 个循环,生成一个新进程并等待hit
消息或超时。之后,server/2
函数结束,server
进程死亡。当它死亡时,名称server
不再注册,因此尝试向其发送消息会生成badarg
错误。