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};