3

这是我的代码:

    lists:foreach(fun(Method, Value)->
                      ServerName = method_to_servername(Method),
                      if
                          Value ==0 andalso whereis(ServerName) =/= undefined ->
                              supervisor:terminate_child(flowrate, whereis(ServerName));
                          Value =/= 0 andalso whereis(ServerName) == undefined ->
                              supervisor:start_child(?MODULE, [Method]);
                          Value =/=0 andalso whereis(ServerName) =/= undefined ->
                              gen_server:call(method_to_servername(Method),
                                              {update_config,
                                               {DesAddress, Method, RateLimitList,
                                                QueueTime,
                                                MinRetry, MaxRetry, Callback}} );
                          true -> ok
                      end
              end, ?ALL_METHODS).

当我编译代码时,我遇到了这个问题: illegal guard expression,你能给我一些建议吗?

4

2 回答 2

3

表达式中的测试if称为保护序列。保护序列中只允许有限数量的功能,而whereis不是其中之一。有关完整列表,请参阅Erlang 参考手册中的 Guard Sequences 部分。

因此,大多数 Erlang 程序员很少使用if. 使用case经常给出更自然和简洁的代码。你的例子可以写成:

lists:foreach(fun(Method, Value)->
                  ServerName = method_to_servername(Method),
                  case {Value, whereis(ServerName)} of
                      {0, ServerPid} when is_pid(ServerPid) ->
                          supervisor:terminate_child(flowrate, ServerPid);
                      {_, undefined} when Value =/= 0 ->
                          supervisor:start_child(?MODULE, [Method]);
                      {_, ServerPid} when is_pid(ServerPid) ->
                          gen_server:call(method_to_servername(Method),
                                          {update_config,
                                           {DesAddress, Method, RateLimitList,
                                            QueueTime,
                                            MinRetry, MaxRetry, Callback}} );
                      _ -> ok
                  end
          end, ?ALL_METHODS).
于 2013-08-31T11:44:45.817 回答
0

使用此代码,您有几个问题:

  1. lists:foreach/2需要以 arity one 作为第一个参数的乐趣,你有两个。我猜你有类似这样定义的 ?ALL_METHODS 宏:-define(ALL_METHODS, [{method1, 1}, {method2, 2}, ...])然后你可以通过在元组中包装 fun 的参数来修复它:fun(Method, Value)将是fun({Method, Value})
  2. 如果你有whereis(ServerName) =/= undefined可能的竞争条件,当首先whereis(ServerName)返回pid()时,然后由于某种原因进程死亡,下一步它将是undefined(但在没有上下文的情况下很难说 100% 确定)。
  3. 你做method_to_servername(Method)两次。

关于您的问题,Erlang 中的保护函数确实只允许某些函数子集

于 2013-09-02T07:44:34.950 回答