模式在Erlang中不匹配

时间:2015-01-20 10:41:37

标签: erlang pattern-matching gen-server

我正在打这个电话:

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

我希望它符合:

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.

但它始终是:

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

怎么了?

2 个答案:

答案 0 :(得分:3)

在使用gen_server行为的模块中,handle_call回调函数应该使用三个参数。但是,您已定义了两个不同的功能handle_call/2handle_call/3。 (在Erlang中,具有相同名称但使用不同数量的参数的函数被视为不同的函数。)

由于gen_server模块只查找handle_call/3并忽略handle_call/2,因此始终会调用“undef”函数。

要解决此问题,请更改函数以获取(忽略的)第二个参数,并将请求放在第一位,将状态放在最后:

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

并将end.更改为end; - .分隔不同的函数,而;分隔同一函数的不同子句。

答案 1 :(得分:2)

行为似乎有效,

handle_call有这样的规范:

-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{}}).

如果你可以看看这里 http://erlang.org/doc/man/gen_server.html#Module:handle_call-3

此外,对于otp默认行为,首先使用模板是最好的。对于gen_server,例如https://gist.github.com/kevsmith/1211350

干杯!