这是我的代码:
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
,你能给我一些建议。
答案 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)
使用此代码,您有几个问题:
lists:foreach/2
需要玩arity one作为第一个参数,你
有两个。我猜你有吗?ALL_METHODS宏定义类似
对此:-define(ALL_METHODS, [{method1, 1}, {method2, 2}, ...])
然后你可以通过在元组中包装fun的参数来修复它:fun(Method, Value)
将是fun({Method, Value})
whereis(ServerName) =/= undefined
你有可能的竞争条件,当whereis(ServerName)
首先返回pid()
时,由于某种原因导致处理死亡,下一步将会undefined
(但如果没有上下文,很难说100%确定。)method_to_servername(Method)
两次。关于你的问题,Erlang中的守卫功能只允许某些subset个功能。