我有以下代码:
-module(circle).
-export([proc/1,mother/0,chain/1]).
-spec mother() -> none().
mother() ->
register(mother,self()).
-spec proc(pid()) -> none().
proc(Next) when is_pid(Next) ->
receive
{_, Msg} -> Next ! {self(), Msg}
end.
-spec chain(integer()) -> pid().
chain(0) -> mother;
chain(N) when is_integer(N) ->
spawn(circle,proc,chain(N-1)).
它按预期编译但是每当我运行时,它会在链到达0
参数时抛出错误的参数错误。这是因为erlang将母亲视为一个原子,但我之前称之为mother
函数应该将mother
注册为pid
。
我最初认为母亲在控制台中打电话后没有注册:
-> circle:mother().
-> mother ! {abc}.
abc
我能够从这里推断出母亲确实得到了像Pid一样的待遇。如何使代码工作?我如何让erlang看到母亲是一个PID?
我想要实现的是在一个圆圈中构建N个进程。
答案 0 :(得分:1)
注册的进程名称不会变成pid。
以下是erlang:send/2中与!
运算符相同的目标类型规范:
dst() = pid()
| port()
| (RegName :: atom())
| {RegName :: atom(), Node :: node()}
如您所见,发送需要多种类型作为目的地。
你不需要关心那个,所以只需要移除那个守卫;为原子案例制作另一个条款或附加到保护orelse is_atom(Next)
。
-spec proc(pid() | atom()) -> none().
proc(Next) ->
receive
{_, Msg} -> Next ! {self(), Msg}
end.
spawn(circle,proc,chain(N-1)).
spawn/3将参数列表作为第三个参数:
spawn(circle,proc,[chain(N-1)]).
我认为注册根进程没有任何好处。如果仅使用pids关闭圆圈是有问题的,那么您可以采用以下方法:
chain(N) ->
chain(N, self()).
chain(0, Mother) -> Mother;
chain(N, Mother) when is_integer(N) ->
spawn(circle,proc,[chain(N-1, Mother)]).
答案 1 :(得分:0)
如果要在mother/0
子句中调用chain(0)
,则必须更正该子句,使其显示为:
chain(0) -> mother();
目前看来,你只是返回一个原子,因为你在函数子句的主体中拥有的只是一个原子,而不是一个函数的调用。例如:
something() -> fun_name. %=> returns `fun_name`
something() -> fun_name(). %=> invokes `fun_name/0` and returns the result of the call.