如何让erlang看到一个原子是一个PID

How to make erlang see that an atom is a PID

我有以下代码:

-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 看到 mother 是一个 PID?

我想实现的是在一个循环中构建N个进程。

如果您想在 chain(0) 子句中调用 mother/0,您必须更正该子句,使其显示为:

chain(0) -> mother();

就目前而言,您只是返回一个原子,因为函数子句的主体中只有一个原子,而不是函数的调用。示例:

something() -> fun_name. %=> returns `fun_name`
something() -> fun_name(). %=> invokes `fun_name/0` and returns the result of the call.

注册的进程名没有变成pid。 这是 erlang:send/2 中目标的类型规范,与 ! 运算符相同:

dst() = pid()
      | port()
      | (RegName :: atom())
      | {RegName :: atom(), Node :: node()}

如您所见,send 将多种类型作为目的地。 你不需要关心那个,所以只要去掉那个守卫就行了;为 atom case 创建另一个子句或附加到 guard 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)]).