【问题标题】:How to make erlang see that an atom is a PID如何让erlang看到一个原子是一个PID
【发布时间】:2015-04-19 15:43:50
【问题描述】:

我有以下代码:

-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 对待。我怎样才能使代码工作?我怎样才能让二郎看到母亲是一个PID?

我想要实现的是在一个圆圈内构建N个流程。

【问题讨论】:

  • 如果我的回答可以解决您的问题,您认为您可以发布异常中的堆栈跟踪吗?

标签: concurrency erlang


【解决方案1】:

注册的进程名不会变成 pid。 这是erlang:send/2 中目的地的类型说明,与! 运算符相同:

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

如您所见,发送需要多种类型作为目的地。 你不需要关心这个,所以只需移除那个守卫;为 atom case 创建另一个子句或附加到保护 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)]).

我认为注册根进程没有任何好处。如果闭环仅对 pid 有问题,您可以这样做:

chain(N) -> 
    chain(N, self()).
chain(0, Mother) -> Mother;
chain(N, Mother) when is_integer(N) ->
    spawn(circle,proc,[chain(N-1, Mother)]).

【讨论】:

    【解决方案2】:

    如果您想在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.
    

    【讨论】:

    • 调用mother() 将尝试将self 注册到原子母亲。这是一个递归调用(可能是一个非常糟糕的调用)所以这 100% 会失败
    • 当我说“坏人”时。我指的是我的函数的递归性质。
    猜你喜欢
    • 2016-05-25
    • 2018-12-09
    • 1970-01-01
    • 2012-11-11
    • 2013-06-04
    • 2011-04-19
    • 2018-09-07
    • 2013-01-01
    • 1970-01-01
    相关资源
    最近更新 更多