在Erlang模块中运行spawns时出错

在Erlang模块中运行spawns时出错,erlang,Erlang,运行此模块时: -module(cbbs). -export([ahu/0, duct/1, simulate/0, room1/1, vent1/0]). duct(P) -> if P>=250 -> apid ! full, io:format("Full Pressure~n", []), receive gia -> vent1 ! {gi

运行此模块时:

-module(cbbs).

-export([ahu/0, duct/1, simulate/0, room1/1, vent1/0]).

duct(P) ->
      if
      P>=250 ->
        apid ! full,
        io:format("Full Pressure~n", []),
        receive
            gia ->
            vent1 ! {gia, self()},
            io:format("Feeding Vent1~n", []),
        duct(P-2)
        end;

      true ->
        apid ! {pressurise, self()},
        receive
            pressurise ->
                io:format("Receiving Pressure~n", []),
                duct(P + 1);
            gia ->
                vent1 ! gia,
                io:format("Feeding Vent1~n", []),
                duct(P - 1)
        end
    end.


ahu() ->
    receive
        full ->
            io:format("Stopped~n", []);
        {pressurise, duct} ->
            io:format("Pressurising~n", []),
                duct ! pressurise,
            ahu()       
    end.


vent1() ->
    receive
        {toohot, room1} ->
            io:format("Open~n", []),
            duct ! gia;

        {roomtemp, room1} ->
            io:format("Closed~n", []);

        {gia, duct} ->
            io:format("Feeding Room1~n", []),
            room1 ! ga,
            vent1()
        end.

room1(T) ->
     if
     T >= 20 ->
           vent1 ! {toohot, self()},
           io:format("R1 Too Hot~n", []),
           receive
            ga ->
            io:format("Cooling R1~n", []),
            room1(T-1)
        end;

     true ->
        vent1 ! {roomtemp, self()},
        io:format("Room Temperature~n", []),
        room1(T+1)

    end.

simulate() ->
        register(apid, spawn(cbbs, ahu, [])),
        register(vent1, spawn(cbbs, vent1, [])),
        register(duct, spawn(cbbs, duct,[0])),
        register(room1, spawn(ccbs, room1, [20])).
我得到这个错误:

cbbs:simulate().
** exception error: bad argument
     in function  register/2
        called as register(apid,<0.292.0>)
     in call from cbbs:simulate/0 (cbbs.erl, line 76)
cbbs:simulate()。
**异常错误:参数错误
在功能寄存器/2中
称为寄存器(apid)
来自cbbs的呼叫中:模拟/0(cbbs.erl,第76行)
我似乎无法进一步理解它对我的要求。这是为了模拟一个并发的建筑服务,并使其在通信方面有点复杂。然而,我无法找出问题所在,因此无法继续找出其他问题

任何帮助都将不胜感激

编辑:

我从第一次跑步中获得以下信息:

=ERROR REPORT==== 10-May-2017::15:36:54 ===
Error in process <0.69.0> with exit value:
{undef,[{ccbs,room1,[20],[]}]}
=错误报告===2017年5月10日::15:36:54===
使用退出值处理时出错:
{undef,[{ccbs,第1房间,[20],]}

然后是前面提到的错误。

如果名称已忙,或者进程在您有时间注册之前已停止,则注册调用可能会失败。您可以使用where is(ProcessName)检查第一个案例,使用erlang:is_process_alive(Pid)检查第二个案例。

您在
simulate()
中的最后一行拼写了模块名
cbbs

第一次运行程序时,该行将出现错误。第二次运行程序时,
simulate()
的第一行将出现错误:

这是因为当你第一次运行你的程序时,你注册的进程会陷入无限循环中,所以在你的程序结束后,它们会永远存在于shell中。因此,当您再次运行
simulate()
时,您尝试注册的名称将已经是正在运行的进程的名称(重新编译没有帮助)。由于程序中存在问题,为了再次运行程序,需要终止erlang shell并启动新的erlang shell。这将终止您第一次运行程序时遗留的进程

试试这个:

  • 纠正拼写错误
  • 启动一个新的erlangshell
  • 运行
    simulate()
  • 使用shell中的
    i()
    命令检查当前正在运行的进程
  • 下面是一个例子:

    $ erl
    Erlang/OTP 19 [erts-8.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]
    
    -----Now, do some Erlang for great Good!------
    
    Eshell V8.2  (abort with ^G)
    
    1> c(cbbs).
    {ok,cbbs}
    
    2> cbbs:simulate().
    R1 Too Hot
    ok
    
    3> i().
    Pid                   Initial Call                          Heap     Reds Msgs
    Registered            Current Function                     Stack              
    <0.0.0>               otp_ring0:start/2                      233      606    0
    init                  init:loop/1                              2              
    <0.1.0>               erts_code_purger:start/0               233        8    0
    erts_code_purger      erts_code_purger:loop/0                  3              
    <0.4.0>               erlang:apply/2                        4185   596196    0
    erl_prim_loader       erl_prim_loader:loop/3                   5              
    <0.30.0>              gen_event:init_it/6                    610      226    0
    error_logger          gen_event:fetch_msg/5                    8              
    <0.31.0>              erlang:apply/2                        1598      416    0
    application_controlle gen_server:loop/6                        7              
    <0.33.0>              application_master:init/4              233       64    0
                          application_master:main_loop/2           6              
    <0.34.0>              application_master:start_it/4          233       59    0
                          application_master:loop_it/4             5              
    <0.35.0>              supervisor:kernel/1                    610     1700    0
    kernel_sup            gen_server:loop/6                        9              
    <0.36.0>              erlang:apply/2                       10958   130910    0
    code_server           code_server:loop/1                       3              
    <0.38.0>              rpc:init/1                             233       21    0
    rex                   gen_server:loop/6                        9              
    <0.39.0>              global:init/1                          233       44    0
    global_name_server    gen_server:loop/6                        9              
    <0.40.0>              erlang:apply/2                         233       21    0
                          global:loop_the_locker/1                 5              
    <0.41.0>              erlang:apply/2                         233        3    0
                          global:loop_the_registrar/0              2              
    <0.42.0>              inet_db:init/1                         233      249    0
    inet_db               gen_server:loop/6                        9              
    <0.43.0>              global_group:init/1                    233       55    0
    global_group          gen_server:loop/6                        9              
    <0.44.0>              file_server:init/1                     376      554    0
    file_server_2         gen_server:loop/6                        9              
    <0.45.0>              supervisor_bridge:standard_error/      233       34    0
    standard_error_sup    gen_server:loop/6                        9              
    <0.46.0>              erlang:apply/2                         233       10    0
    standard_error        standard_error:server_loop/1             2              
    <0.47.0>              supervisor_bridge:user_sup/1           233       53    0
                          gen_server:loop/6                        9              
    <0.48.0>              user_drv:server/2                     1598     3850    0
    user_drv              user_drv:server_loop/6                   9              
    <0.49.0>              group:server/3                         233      210    0
    user                  group:server_loop/3                      4              
    <0.50.0>              group:server/3                         987    13450    0
                          group:server_loop/3                      4              
    <0.51.0>              erlang:apply/2                        4185     9974    0
                          shell:shell_rep/4                       17              
    <0.52.0>              kernel_config:init/1                   233      193    0
                          gen_server:loop/6                        9              
    <0.53.0>              supervisor:kernel/1                    233       56    0
    kernel_safe_sup       gen_server:loop/6                        9              
    <0.57.0>              erlang:apply/2                        1598    20441    0
                          c:pinfo/1                               50              
    <0.64.0>              cbbs:ahu/0                             233        2    1
    apid                  cbbs:ahu/0                               1              
    <0.65.0>              cbbs:vent1/0                           233        2    1
    vent1                 cbbs:vent1/0                             1              
    <0.66.0>              cbbs:duct/1                            233        2    0
    duct                  cbbs:duct/1                              2              
    <0.67.0>              cbbs:room1/1                           233       15    0
    room1                 cbbs:room1/1                             2              
    Total                                                      31365   779424    2
                                                                 228              
    ok
    4> 
    
    该列列出了shell中当前运行的进程的所有进程标识符(Pid),以及Pid下的进程注册名称(如果进程已注册)。您可以看到您注册的进程列在第一列的底部。您的程序已终止,但这些进程仍在shell中运行

    i()
    输出中,第二列的标题为:

    Pid
    Registered
    
    Initial Call
    Current Function
    
    Initial Call
    是您为启动流程而调用的函数,例如
    spawn(ccbs,room1,[20])
    ,下面是该流程中当前正在执行的函数。例如,如果
    room1()

    cbbs:room1/1
    cbbs:loop/1
    

    进程陷入无限循环的原因是接收子句中的模式有缺陷。例如,当您在此处发送消息时:

    room1(T) ->
         if
         T >= 20 ->
               vent1 ! {toohot, self()},
    
    self()
    不返回
    room1
    ,因此在receive子句中:

    vent1() ->
        receive
            {toohot, room1} ->
                io:format("Open~n", []),
                duct ! gia;
    
    模式
    {toohot,room1}
    将与
    room1()
    发送的消息不匹配
    self()。转换为字符串作为输出的Pid如下所示:
    (但请记住Pid不是字符串,因此不能在Pid的代码中写入
    “”

    您需要更改receive子句中的模式。您可以将模式更改为:

    vent1() ->
        receive
            {toohot, _From} ->  #<*** HERE
                io:format("Open~n", []),
                duct ! gia;
    
    vent1() ->
        Room1 = whereis(room1),  #<***HERE
        receive
            {toohot, Room1} ->   #<***AND HERE
                io:format("Open~n", []),
                duct ! gia;
    
    函数子句按照它们在代码中的写入顺序进行匹配。因此,当您调用
    room1()
    时,第一个erlang将尝试匹配function子句:

    room1(T) when T >= 20 ->
    
    room1(T) ->
    
    如果
    T
    小于20,则该函数子句将不匹配,因此erlang将继续执行下一个函数子句:

    room1(T) when T >= 20 ->
    
    room1(T) ->
    
    该function子句将匹配任何单个参数,因此它将执行。请注意,分号分隔函数子句而不是句点。如果意外使用句点,则会出现以下错误:

    功能室1/1已定义

    如果您觉得首先编写一个
    If语句
    是很自然的,那么就继续这样做吧……但要立即将
    If语句
    转换为一系列
    函数子句
    。在你做了一段时间的转换之后,我认为你的思维将适应于从
    函数子句
    而不是
    if语句
    的角度来思考


    还有,我看到你在做我以前做过的事情:

    io:format("R1 Too Hot~n", []),
    
    还有一个额外的单参数形式
    io:format()
    ,因此您只需编写:

    io:format("R1 Too Hot~n"),
    

    输入起来不那么痛苦。

    看起来在该行执行之前,另一个进程已经注册为
    apid
    。感谢您的回复!这很奇怪,因为当我模拟时它返回true,然后打印以下内容:=错误报告====2017年5月10日::15:36:54===进程中的错误,退出值:{unde,[{ccbs,room1,[20],]}}如果我再次模拟,它会给我前面提到的错误,进程应该自行注册(因为它知道它没有死…),你应该使用
    ?模块
    宏。初学者应该始终使用
    ?模块
    宏;它可以防止拼写错误。非常感谢你@7stud!!!绝对令人惊讶的答案。现在就尝试让它工作:)@GabrielSeite,如果你遇到更多问题,发表一篇针对我的评论,我会再看看你的节目。祝你好运@7stud感谢您的帮助,我已设法使系统与3个通风口和3个房间同时运行。如果您想要解决方案,请告诉我,我很乐意按您的方式发送!
    
    io:format("R1 Too Hot~n"),