关于Erlang语言中“if”的用法

时间:2013-08-31 08:58:52

标签: if-statement erlang

这是我的代码:

    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,你能给我一些建议。

2 个答案:

答案 0 :(得分:3)

if表达式中的测试称为保护序列。保护序列中只允许有限数量的功能,而whereis不是其中之一。有关完整列表,请参阅the section on Guard Sequences in the Erlang Reference Manual

因此,大多数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).

答案 1 :(得分: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)两次。
  4. 关于你的问题,Erlang中的守卫功能只允许某些subset个功能。