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

时间:2015-02-18 15:17:23

标签: concurrency erlang

我有以下代码:

-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个进程。

2 个答案:

答案 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.