Erlang:强迫公开方法,为什么?

day*_*mer 2 erlang

我正在关注Joe Armstrong的书Programming Erlang, 2nd Edition,我们在那里制作文件服务器.

我的代码:

-module(afile_server).
-author("harith").

%% API
-export([start/1]).

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

loop(Dir) ->
    receive
        {Client, list_dir}  ->
            Client ! {self(), file:list_dir(Dir)};
        {Client, {get_file, File}}  ->
            File_Path = filename:join(Dir, File),
            Client ! {self(), file:read_file(File_Path)}
    end,
    loop(Dir).
Run Code Online (Sandbox Code Playgroud)

我们可以看到,这loop是一种私有方法,不应暴露于外部世界.现在当我运行这个时,我得到:

1> FileServer = afile_server:start(".").
<0.33.0>

=ERROR REPORT==== 3-Jan-2015::06:58:56 ===
Error in process <0.33.0> with exit value: {undef,[{afile_server,loop,["."],[]}]}

2> 
Run Code Online (Sandbox Code Playgroud)

但当我loop公开时:

-module(afile_server).
-author("harith").

%% API
-export([start/1, loop/1]).

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

loop(Dir) ->
    receive
        {Client, list_dir}  ->
            Client ! {self(), file:list_dir(Dir)};
        {Client, {get_file, File}}  ->
            File_Path = filename:join(Dir, File),
            Client ! {self(), file:read_file(File_Path)}
    end,
    loop(Dir).
Run Code Online (Sandbox Code Playgroud)

然后运行正常:

1> FileServer = afile_server:start(".").
<0.33.0>
2> 
Run Code Online (Sandbox Code Playgroud)

是否spawn要求公开方法?我想是的,因为它运行它:

afile_server:loop(Dir)  
Run Code Online (Sandbox Code Playgroud)

但我想确保没有别的错.

use*_*836 5

如果你使用spawn与M:F:A你被迫设置循环公共.

你可以这样避免它:

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

start(Dir) ->  spawn(fun() -> loop(Dir) end).

loop(Dir) ->
    receive
        {Client, list_dir}  ->
            Client ! {self(), file:list_dir(Dir)};
        {Client, {get_file, File}}  ->
            File_Path = filename:join(Dir, File),
            Client ! {self(), file:read_file(File_Path)}
    end,
    loop(Dir).
Run Code Online (Sandbox Code Playgroud)

如果您的方法没有参数,您也可以使用:

spawn(fun loop/0),
Run Code Online (Sandbox Code Playgroud)

将该版本与M:F:A一起使用的一个很好的理由在于,无论何时加载同一模块的新版本,都将调用此新版本.否则你将继续调用旧模块.