2014-10-29 2 views
0

Erlang 모듈에 문제가 있습니다. 여기에 제가 작성한 것이 있습니다 :Erlang 기본 일반 서버 디버거 출력 해석

-module (basic_gen_server). -export ([시작/1, 통화/2, 캐스트/2]). 나는 다음과 같은 디버그 출력을 얻을

MyServer = basic_gen_server:start(name_server). 

: 다음 명령을 실행하여 서버를 초기화하는시

% 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}. 

: 여기

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. 

그리고

는 정의 된 콜백 모듈

=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

답변

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 아톰). 기능이 {basic_gen_server,gen_server_loop,[name_server,#{}],[]}이거나 {Module, Function, ListOfArgs, ...} 인 곳 당신은 항상

  • 이 (오류 메시지 목록) 어떤 종류의 모듈이나 함수 이름을 호출 인수
  • 기능 arity에 일치하는 번호가없는

  • 기능이 수출되어 있는지 확인해야한다

모든 지역을 함수가 정의되어 있지 않으면 (모듈이 지정되지 않은 loop(SomeArgs)과 같은) 호출은 컴파일되지 않습니다. 그리고 동적으로 로컬 콜을 할 수 있습니다 (FuntionName(SomeArgs) 다시 모듈 이름없이).


지역 통화의 필요성에 대한 코멘트 후 편집.

실제로 람다를 사용할 수 있습니다. spawn/1 funciton이 있는데 람다 (또는 원하는 경우 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를 내보내기를 원합니다. 모듈 인터페이스에서 숨겨져 있어야하는 루프 함수를 내보내는 것을 피할 수있는 방법이 있습니까? –