0

我在使用 Erlang 模块时遇到了一些问题。这是我写的:

-模块(basic_gen_server)。-出口([开始/1,呼叫/2,演员/2])。

start(Module) ->
    register(server, spawn(basic_gen_server,gen_server_loop,[Module, Module:init()])), server.

call(Pid,Request) -> 
    Pid ! {call, self(), Request},
    receive
        Reply -> Reply
    end.

cast(Pid,Request) ->
    Pid ! {cast, self(), Request},
    receive
        _ -> ok
    end.

gen_server_loop(Module, CurrentState) -> 
    io:fwrite("gen_server_loop~n", []),
    receive
        {call, CallPid, Request} -> 
            {reply, Reply, NewState} = Module:handle_call(Request,self(),CurrentState),
            CallPid ! Reply,
            gen_server_loop(Module, NewState);
        {cast, CastPid, Request} ->
            {noReply, NewState} = Module:handle_cast(Request, CurrentState),
            CastPid ! noReply,
            gen_server_loop(Module, NewState)
    end.

这是定义的回调模块:

% Written by Caleb Helbling
% Last updated Oct 10, 2014

-module(name_server).
-export([init/0, add/3, whereis/2, handle_cast/2,
         handle_call/3, handle_swap_code/1]).

%% client routines

add(ServerPid, Person, Place) ->
    basic_gen_server:cast(ServerPid, {add, Person, Place}).

whereis(ServerPid, Person) ->
    basic_gen_server:call(ServerPid, {whereis, Person}).

%% callback routines

init() ->
    maps:new().

handle_cast({add, Person, Place}, State) ->
    NewState = maps:put(Person, Place, State),
    {noreply, NewState}.

handle_call({whereis, Person}, _From, State) ->
    Reply = case maps:find(Person, State) of
        {ok, Place} -> Place;
        error -> error
    end,
    NewState = State,
    {reply, Reply, NewState}.

handle_swap_code(State) ->
    {ok, State}.

尝试使用以下命令初始化服务器时:

MyServer = basic_gen_server:start(name_server).

我得到以下调试输出:

=ERROR REPORT==== 29-Oct-2014::12:41:42 ===
Error in process <0.70.0> with exit value: {undef,[{basic_gen_server,gen_server_loop,[name_server,#{}],[]}]}

从概念上讲,我理解将串行代码制作成基本服务器系统的概念,但我相信我有一个语法错误,我无法使用语法高亮或谷歌找到它。在此先感谢您的帮助!

4

1 回答 1

1

函数gen_server_loop未导出。所以你不能打电话basic_gen_server:gen_server_loop(Module, Module:init()),这是里面发生的事情 spawn(basic_gen_server,gen_server_loop,[Module, Module:init()])

如果您阅读错误消息,它会告诉您您尝试在未定义(trougn undefatom)中调用的函数。功能在{basic_gen_server,gen_server_loop,[name_server,#{}],[]}哪里,还是在哪里{Module, Function, ListOfArgs, ...}。你总是应该检查

  • 没有类型模块或函数名称
  • 函数arity匹配调用中的参数数量(错误消息中的列表)
  • 函数被导出

如果未定义函数,则所有本地调用(例如loop(SomeArgs),未指定模块)都不会编译。您可以动态地进行本地调用(FuntionName(SomeArgs)再次没有模块名称)。


在评论需要本地电话后进行编辑。

您实际上可以为此使用 lambda。有函数spawn/1,它需要 lambda(或者fun如果你喜欢),所以你可以调用spawn( fun local_functino/0).. 唯一的问题是你fun不能接受任何参数,但是有一种方法可以解决它,使用闭包。

spawn(fun () ->
         gen_server_loop(Module, Module:init())
      end).

gen_serve_loop保持本地通话。

于 2014-10-29T16:57:13.287 回答