2014-10-29 31 views
0

我在使用Erlang模塊時遇到了一些麻煩。這裏是我寫的:Erlang基本通用服務器調試器輸出解釋

-module(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找到它。先謝謝您的幫助!

+0

一句話與你的問題無關,我想你應該在gen_server轉換接口中刪除接收塊。它會使演員同步。只需更換即可。 – Pascal 2014-10-30 08:11:06

回答

1

功能gen_server_loop未導出。所以你不能撥打basic_gen_server:gen_server_loop(Module, Module:init()),這是spawn(basic_gen_server,gen_server_loop,[Module, Module:init()])內部發生的事情。

如果您閱讀了錯誤消息,它會告訴您未嘗試調用的函數(常規原子undef)。函數是{basic_gen_server,gen_server_loop,[name_server,#{}],[]},或者你有{Module, Function, ListOfArgs, ...}。你總是應該檢查

  • 沒有類型的模塊或函數名在調用的參數
  • 功能參數數量匹配號碼(在錯誤信息列表)
  • 功能導出

所有地方如果未定義函數,則調用(如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保持本地通話。

+0

我明白導出它的用法,但我們的任務明確希望我們僅導出程序中的某些函數,即start/1,call/3和cast/2。有沒有辦法避免導出循環函數,這應該是隱藏的模塊接口? – 2014-10-29 17:05:03