Alexander Shavelev
Alexander Shavelev

Reputation: 324

Pattern not matching in Erlang

I'm making this call:

add(Login, Pass, Role) ->
  gen_server:call(?SERVER, {add, Login, Pass, Role}).

and I expect it to match with:

handle_call(State, {add, Login, Pass, Role}) ->
  io:format("add ~n"),
  Db = State#state.db,
  case lists:keyfind(Login, 1, Db) of
    false->
      io:format("add - reg new ~n"),
      {reply, registered, State#state{db=[{Login, erlang:md5(Pass), Role, ""}|Db]}};
     {Key, Result}-> 
      {reply, invalid_params, Db}  
  end.

but it always goes to:

handle_call(_Request, _From, State) ->
  io:format("undef ~n"),
  Reply = ok,
  {reply, Reply, State}.

What's wrong?

Upvotes: 2

Views: 261

Answers (2)

legoscia
legoscia

Reputation: 41528

In a module using the gen_server behaviour, the handle_call callback function should take three arguments. However, you have defined two different functions, handle_call/2 and handle_call/3. (In Erlang, functions that have the same name but take different numbers of arguments are considered different functions.)

Since the gen_server module only looks for handle_call/3 and ignores handle_call/2, your "undef" function is always called.

To fix this, change the function to take an (ignored) second argument, and put the request first and the state last:

handle_call({add, Login, Pass, Role}, _From, State) ->

and change the end. to end;. separates different functions, while ; separates different clauses of the same function.

Upvotes: 3

Evan P
Evan P

Reputation: 1817

The behaviour seems valid,

handle_call has such spec:

-spec(handle_call(Request :: term(), From :: {pid(), Tag :: term()},
    State :: #state{}) ->
  {reply, Reply :: term(), NewState :: #state{}} |
  {reply, Reply :: term(), NewState :: #state{}, timeout() | hibernate} |
  {noreply, NewState :: #state{}} |
  {noreply, NewState :: #state{}, timeout() | hibernate} |
  {stop, Reason :: term(), Reply :: term(), NewState :: #state{}} |
  {stop, Reason :: term(), NewState :: #state{}}).

If you can take a look here http://erlang.org/doc/man/gen_server.html#Module:handle_call-3

Also, for otp default behaviours, it would be the best, as a start, to use templates. For gen_server eg https://gist.github.com/kevsmith/1211350

Cheers!

Upvotes: 3

Related Questions