编程Erlang(第二,阿姆斯特朗)第15-18页:为什么shell在第二次接收后挂起?

编程Erlang(第二,阿姆斯特朗)第15-18页:为什么shell在第二次接收后挂起?,erlang,erlang-shell,Erlang,Erlang Shell,这是我的密码: -module(afile_server). -export([start/1, loop/1]). start(Dir) -> spawn(afile_server, loop, [Dir]). loop(Dir) -> receive {Client, list_files} -> Client ! {self(), file:list_dir(Dir)}; {Client, {

这是我的密码:

-module(afile_server).
-export([start/1, loop/1]).

start(Dir) -> 
    spawn(afile_server, loop, [Dir]).

loop(Dir) ->
    receive
        {Client, list_files} -> 
            Client ! {self(), file:list_dir(Dir)};
        {Client, {get_file, File}} -> 
            Full = filename:join(Dir, File),
            Client ! {self(), file:read_file(Full)}
    end,
    loop(Dir).
以下是shell命令:

$ erl
Erlang/OTP 17 [erts-6.4] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V6.4  (abort with ^G)

2> c(afile_server).
{ok,afile_server}

3> Server = afile_server:start(".").
<0.43.0>

4> Server ! {self(), list_files}.
{<0.32.0>,list_files}

5> receive X -> X end. 
{<0.43.0>,
 {ok,["afile_client.erl","afile_server.beam",
      "afile_server.erl","hello.beam","hello.erl","old"]}}

6> Server ! {self(), {get_file, "hello.erl"}}.
{<0.32.0>,{get_file,"hello.erl"}}

7> receive X -> X end.

<hangs>
$erl
Erlang/OTP 17[erts-6.4][source][64位][smp:4:4][async threads:10][hipe][kernel poll:false]
Eshell V6.4(使用^G中止)
2> c(文件服务器)。
{好的,文件服务器}
3> 服务器=文件服务器:开始(“.”)。
4> 服务器!{self(),列出_文件}。
{,列出_文件}
5> 接收X->X结束。
{,
{好的,[“afile_client.erl”,“afile_server.beam”,
“afile_server.erl”、“hello.beam”、“hello.erl”、“old”]}
6> 服务器!{self(),{get_file,“hello.erl”}。
{,{get_文件,“hello.erl”}
7> 接收X->X结束。

好的,我在这里找到了答案:

谢谢安德斯·尼格伦

对于第一次接收,X从未绑定开始,它将匹配任何内容。当第一个receive检查来自文件服务器的消息时,X将绑定到该消息,该值为:

 {ok,["afile_client.erl","afile_server.beam",
      "afile_server.erl","hello.beam","hello.erl","old"]}}
在第二次接收中,X已绑定,因此接收正在查找与以下项匹配的项:

 {ok,["afile_client.erl","afile_server.beam",
      "afile_server.erl","hello.beam","hello.erl","old"]}}
第二个接收挂起,因为文件服务器发送的消息为:

{ok,<<"-module(hello).\n-export([start/0]).\n\nstart() ->
    io:format(\"hello world~n\").\n">>}}

好的,我在这里找到了答案:

谢谢安德斯·尼格伦

对于第一次接收,X从未绑定开始,它将匹配任何内容。当第一个receive检查来自文件服务器的消息时,X将绑定到该消息,该值为:

 {ok,["afile_client.erl","afile_server.beam",
      "afile_server.erl","hello.beam","hello.erl","old"]}}
在第二次接收中,X已绑定,因此接收正在查找与以下项匹配的项:

 {ok,["afile_client.erl","afile_server.beam",
      "afile_server.erl","hello.beam","hello.erl","old"]}}
第二个接收挂起,因为文件服务器发送的消息为:

{ok,<<"-module(hello).\n-export([start/0]).\n\nstart() ->
    io:format(\"hello world~n\").\n">>}}

在模块函数中,您必须使用接收块来访问消息,而在shell中,有一个预定义的函数可以打印到目前为止收到的所有消息:flush(),如果消息队列为空,它也会立即返回。如果您想阅读一条消息,您必须使用您的方法,然后您可以利用在shell中模拟te变量赋值的优势,因此有可能忘记一条消息:f(X)和X将被考虑unbound@Pascal,感谢您的提示。在模块功能中,您必须使用接收块才能访问消息,在shell中有一个预定义的函数,用于打印到目前为止收到的所有消息:flush(),如果消息队列为空,它也会立即返回。如果您想阅读一条消息,您必须使用您的方法,然后您可以利用在shell中模拟te变量赋值的优势,因此有可能忘记一条消息:f(X)和X将被考虑unbound@Pascal,谢谢你的提示。