【问题标题】:Erlang basic general server debugger output interpretationErlang基本通用服务器调试器输出解释
【发布时间】:2014-10-30 01:31:52
【问题描述】:

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

-模块(basic_gen_server)。 -export([start/1, call/2, cast/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,#{}],[]}]}

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

【问题讨论】:

  • 与您的问题无关的一句话,我认为您应该删除 gen_server 演员界面中的接收块。它使演员表是同步的。只需替换为 ok。

标签: erlang gen-server


【解决方案1】:

函数gen_server_loop 未导出。所以你不能调用basic_gen_server:gen_server_loop(Module, Module:init()),这是spawn(basic_gen_server,gen_server_loop,[Module, Module:init()])内部发生的事情。

如果您阅读了错误消息,它会告诉您您尝试在未定义中调用的函数(trougn undef atom)。函数是{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 保持本地通话。

【讨论】:

  • 我了解导出它的用途,但我们的任务明确希望我们只导出程序中的某些函数,即 start/1、call/3 和 cast/2。有没有办法避免导出应该从模块界面隐藏的循环函数?
猜你喜欢
  • 1970-01-01
  • 2016-08-15
  • 1970-01-01
  • 2019-02-18
  • 2019-10-14
  • 2010-09-29
  • 2014-11-08
  • 1970-01-01
  • 2014-04-08
相关资源
最近更新 更多