简体   繁体   中英

Returning State from a gen_server cast

I am following http://learnyousomeerlang.com/static/erlang/kitty_gen_server.erl .

I have my application logic inside of temple.erl. All of this code is tested & runs as I expect it to. My land.erl is intended to be the server that contains the Temple.

My understanding (please correct any ignorance) is that I can use gen_server to abstract message passing and keep track of state with minimal overhead.

I understand that the second tuplevalue in my init function

init([]) -> {ok, temple:new()}. is my server's state - in this case, the return value of temple:new() .

So I c(land) . (code below), and try this:

19> {ok, Pid2} = land:start_link().
{ok,<0.108.0>}
20> land:join(Pid2, a).
ok

and I just get the atom ok back when I send the join message From reading the code and comparing my experiences running the kitty_gen_server, I think the state is updated correctly with the value temple:join(Temple, Name) , but the ok atom is the response value from

handle_call({join, Name}, _From, Temple) ->
{reply, ok, temple:join(Temple, Name)};

how can I update my state with temple:join(Temple, Name), and then return this value to the client? I don't want to call the same function twice eg.

handle_call({join, Name}, _From, Temple) ->
{reply, temple:join(Temple, Name), temple:join(Temple, Name)};

So looking at the kitty_gen_server I tried

handle_call({join, Name}, _From, Temple) ->
[{reply, JoinedTemple, JoinedTemple} || JoinedTemple <- temple:join(Temple, Name)];

and I get a function clause crash when I try this with a message about syntax error ||, and then I see this is only for list comprehensions..

how can I compute the value of temple:join(Temple, Name)] and return to the caller of land:join and update the Land's state?

-module(land).
-behaviour(gen_server).

-export([start_link/0, join/2, input/3, fight/1]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
         terminate/2, code_change/3]).

start_link() ->
    gen_server:start_link(?MODULE, [], []).

join(Pid, Name) ->
   gen_server:call(Pid, {join, Name}).

input(Pid, Action, Target) ->
    gen_server:call(Pid, {input, Action, Target}).

fight(Pid) ->
    gen_server:call(Pid, fight).

init([]) -> {ok, temple:new()}.

handle_call({join, Name}, _From) ->
  {reply, ok, temple:join(Name)}.
handle_call({join, Name}, _From, Temple) ->
  {reply, temple:join(Temple, Name), temple:join(Temple, Name)};
handle_call(terminate, _From, Temple) ->
    {stop, normal, ok, Temple}.

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

terminate(normal, Temple) ->
    io:format("Temple bathed in blood.~p~n", [Temple]),
    ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}. 

handle_cast(_, Temple) ->
    {noreply, Temple}.

You can store the new state in a variable and then return a tuple containing that variable twice:

handle_call({join, Name}, _From, Temple) ->
  NewTemple = temple:join(Temple, Name),
  {reply, NewTemple, NewTemple};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM