【问题标题】:Function clause error Erlang函数子句错误 Erlang
【发布时间】:2018-11-29 00:53:28
【问题描述】:

我正在尝试理解 erlang 中的进程通信。这里我有一个主进程和五个好友进程。如果朋友向其他 5 个中的任何一个发送消息,他们必须回复。但是主人应该知道这一切。我正在粘贴下面的代码。

-module(prog).
-import(lists,[append/2,concat/1]).

-import(maps,[from_lists/1,find/2,get/2,update/3]).
-import(string,[equal/2]).
-import(file,[consult/1]).
-export([create_process/1,friends/4, master/1, main/0,prnt/1]).     



%% CREATE PROCESS 
create_process([])->ok;
create_process([H|T])->
    {A,B} = H,
    Pid = spawn(prog,friends,[B,self(),0,A]),
    register(A,Pid),
    create_process(T).


%% FRIENDS PROCESS
friends(Msg, M_pid, State, Self_name)->
    S = lists:concat([Self_name," state =",State,"\n"]),
    io:fwrite(S),
    if
        State == 0 ->
            timer:sleep(500),
            io:fwrite("~p~n",[Self_name]),
            lists:foreach(fun(X) -> whereis(X)!{Self_name,"intro",self()} end, Msg),
            friends(Msg, M_pid, State + 1, Self_name);
        State > 0 ->
            receive
                {Process_name, Process_msg, Process_id} -> 
                    I = equal(Process_msg,"intro"),
                    R = equal(Process_msg,"reply"),
                    XxX = lists:concat([Self_name," recieved ",Process_msg," from ",Process_name,"\n"]),
                    io:fwrite(XxX),
                    if
                        I == true ->
                            io:fwrite("~p~n",[whereis(Process_name)]),
                            M_pid!{lists:concat([Self_name," received intro message from ", Process_name , "[",Process_id,"]"]), self()},
                            io:fwrite(I),
                            whereis(Process_name)!{Self_name, "reply",self()},

                            friends(Msg, M_pid, State + 1, Self_name);
                        R == true ->
                            M_pid!{lists:concat([Self_name," received reply message from ", Process_name , "[",Process_id,"]"]), self()},
                            io:fwrite(R),
                            friends(Msg, M_pid, State + 1, Self_name)
                    end
            after
                1000->
                    io:fwrite(lists:concat([Self_name," has received no calls for 1 second, ending..."]))
            end

    end.


master(State)->
    receive
        {Process_message, Process_id} ->
            io:fwrite(Process_message),
            master(State+1)
    after
        2000->
            ok
    end.


main() ->
    B = [{john, [jill,joe,bob]},
{jill, [bob,joe,bob]},
{sue, [jill,jill,jill,bob,jill]},
{bob, [john]},
{joe, [sue]}],
    create_process(B),
    io:fwrite("~p~n",[whereis(sue)]),

    master(0).

我认为friends()函数中的那一行,

M_pid!{lists:concat([Self_name," received intro message from ", Process_name , "[",Process_id,"]"]), self()}

是错误的原因,但我不明白为什么。 M_pid 是已知的,我正在连接所有信息并将其发送给 master,但我很困惑为什么它不起作用。

我得到的错误如下:

Error in process <0.55.0> with exit value: {function_clause,[{lists,thing_to_list,
                         [<0.54.0>],
                         [{file,"lists.erl"},{line,603}]},
                  {lists,flatmap,2,[{file,"lists.erl"},{line,1250}]},
                  {lists,flatmap,2,[{file,"lists.erl"},{line,1250}]},
                  {prog,friends,4,[{file,"prog.erl"},{line,45}]}]}

我不知道是什么导致了错误。很抱歉向菜鸟提问,感谢您的帮助。

【问题讨论】:

  • 尝试在对lists:concat/2的调用中将Process_id更改为pid_to_list(Process_id)
  • 嗨,Dogbert。我会回家试一试。但出于好奇,有什么区别?为什么 Process_id 搞砸了 list:concat/2 ?
  • 您报告的错误消息看起来与代码段不一致(第 45 行或其他任何地方没有列表:flatmap/2 调用)。我有 2 条评论: 1/ 你在 after 子句中没有递归调用,所以如果一个进程遇到这个子句,它将停止。 2/ 使用 import 指令是非常不寻常的,通常,erlang 程序员更喜欢显式显示完全限定的调用(就像你一样),在这种情况下 import 指令是无用的。

标签: functional-programming erlang


【解决方案1】:

我运行了你的代码。 你出错的地方是将Process_id(类型为pid())传递给lists:concat/1

让我们试着理解这个错误:

{function_clause,[{lists,thing_to_list,
                         [<0.84.0>],
                         [{file,"lists.erl"},{line,603}]},
                  {lists,flatmap,2,[{file,"lists.erl"},{line,1250}]},
                  {lists,flatmap,2,[{file,"lists.erl"},{line,1250}]},
                  {prog,friends,4,[{file,"prog.erl"},{line,39}]}]}

它指出函数 lists:thing_to_list/1 没有定义(请参阅错误日志中的单词 function_clause),它接受 pid() 类型的参数,如这里由 [&lt;0.84.0&gt;] 表示。

字符串在 erlang 中表示为列表,这就是我们使用 lists:concat/1 的原因。

正如@7stud 指出的,这些是可以根据documentation 传递给lists:concat/1 的有效类型:

atom() | integer() | float() | string()

以下行出现了 2 次。修复它们,你就可以开始了:

代码不正确:

M_pid!{lists:concat([Self_name," received intro message from ", Process_name , "[",Process_id,"]"]), self()},

更正的代码

M_pid!{lists:concat([Self_name," received intro message from ", Process_name , "[",pid_to_list(Process_id),"]"]), self()},

注意函数erlang:pid_to_list/1的使用。根据documentation,该函数接受pid() 类型并将其返回为string()

【讨论】:

    【解决方案2】:

    Dogbert 发现的一个例子:

    -module(my).
    -compile(export_all).
    
    go() ->
        Pid = spawn(my, nothing, []),
        lists:concat(["hello", Pid]).
    
    
    nothing() -> nothing.
    

    在外壳中:

    2> c(my).
    my.erl:2: Warning: export_all flag enabled - all functions will be exported
    {ok,my}
    
    3> my:go().
    ** exception error: no function clause matching 
                        lists:thing_to_list(<0.75.0>) (lists.erl, line 603)
         in function  lists:flatmap/2 (lists.erl, line 1250)
         in call from lists:flatmap/2 (lists.erl, line 1250)
    4> 
    

    但是:

    -module(my).
    -compile(export_all).
    
    go() ->
        Pid = spawn(my, nothing, []),
        lists:concat(["hello", pid_to_list(Pid)]).
    
    nothing() -> nothing.
    

    在外壳中:

    4> c(my).  
    my.erl:2: Warning: export_all flag enabled - all functions will be exported
    {ok,my}
    
    5> my:go().
    "hello<0.83.0>"
    

    来自erl docs

    concat(Things) -> string()
        Things = [Thing]
        Thing = atom() | integer() | float() | string()
    

    您提供给 concat() 的列表必须包含原子、整数、浮点数或字符串。 pid 既不是原子、整数、浮点数或字符串,所以 pid 不能与 concat() 一起使用。但是,pid_to_list() 返回一个字符串:

    pid_to_list(Pid) -> string()
        Pid = pid()
    

    如您所见,pid 有自己的类型:pid()。

    【讨论】:

      猜你喜欢
      • 2021-04-03
      • 2015-01-14
      • 1970-01-01
      • 1970-01-01
      • 2014-10-24
      • 2015-03-20
      • 1970-01-01
      • 2018-09-03
      • 1970-01-01
      相关资源
      最近更新 更多