Erlang R19中的gen_server实现

时间:2016-09-16 15:21:19

标签: erlang

我从Learn you some erlang for great good复制gen_server实现代码,并创建一个名为kitty_gen_server.erl的文件。然后我在erlang shell中运行以下命令:

$ erl
Erlang/OTP 19 [erts-8.0.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Eshell V8.0.2  (abort with ^G)
1> c(kitty_gen_server).
{ok,kitty_gen_server}
2> P = kitty_gen_server:start_link().
{ok,<0.64.0>}
3> kitty_gen_server:close_shop(P).
** exception exit: {{function_clause,
                        [{gen,do_for_proc,
                             [{ok,<0.64.0>},#Fun<gen.0.62797829>],
                             [{file,"gen.erl"},{line,253}]},
                         {gen_server,call,2,[{file,"gen_server.erl"},{line,200}]},
                         {erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,674}]},
                         {shell,exprs,7,[{file,"shell.erl"},{line,686}]},
                         {shell,eval_exprs,7,[{file,"shell.erl"},{line,641}]},
                         {shell,eval_loop,3,[{file,"shell.erl"},{line,626}]}]},
                    {gen_server,call,[{ok,<0.64.0>},terminate]}}
     in function  gen_server:call/2 (gen_server.erl, line 204)
4>

我确信代码是从learn you some erlang for greate good下载的,但我不知道为什么不能执行。

我的系统是OS X 10.11,Erlang 19。

以下是代码:

-module(kitty_gen_server).
-behaviour(gen_server).

-export([start_link/0, order_cat/4, return_cat/2, close_shop/1]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
         terminate/2, code_change/3]).

-record(cat, {name, color=green, description}).

%%% Client API
start_link() ->
    gen_server:start_link(?MODULE, [], [{debug,[trace]}]).

%% Synchronous call
order_cat(Pid, Name, Color, Description) ->
   gen_server:call(Pid, {order, Name, Color, Description}).

%% This call is asynchronous
return_cat(Pid, Cat = #cat{}) ->
    gen_server:cast(Pid, {return, Cat}).

%% Synchronous call
close_shop(Pid) ->
    gen_server:call(Pid, terminate).

%%% Server functions
init([]) -> {ok, []}. %% no treatment of info here!

handle_call({order, Name, Color, Description}, _From, Cats) ->
    if Cats =:= [] ->
        {reply, make_cat(Name, Color, Description), Cats};
       Cats =/= [] ->
        {reply, hd(Cats), tl(Cats)}
    end;
handle_call(terminate, _From, Cats) ->
    {stop, normal, ok, Cats}.

handle_cast({return, Cat = #cat{}}, Cats) ->
    {noreply, [Cat|Cats]}.

handle_info(Msg, Cats) ->
    io:format("Unexpected message: ~p~n",[Msg]),
    {noreply, Cats}.

terminate(normal, Cats) ->
    [io:format("~p was set free.~n",[C#cat.name]) || C <- Cats],
    ok.

code_change(_OldVsn, State, _Extra) ->
    %% No change planned. The function is there for the behaviour,
    %% but will not be used. Only a version on the next
    {ok, State}. 

%%% Private functions
make_cat(Name, Col, Desc) ->
    #cat{name=Name, color=Col, description=Desc}.

1 个答案:

答案 0 :(得分:4)

kitty_gen_server:start_link/0会在成功时返回一个元组{ok, Pid},您可以直接在[{1}}中存储,因此您的下一个电话会将P传递给{ok, Pid}只是Pid。您需要使用模式匹配仅将Pid存储在kitty_gen_server:close_shop/1

P