This is my code:
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).
when i compile the code, i meet this problem :illegal guard expression
, can you give me some advise.
The tests in an if
expression are called guard sequences. Only a limited number of functions are allowed in guard sequences, and whereis
is not one of them. See the section on Guard Sequences in the Erlang Reference Manual for the complete list.
As a consequence, most Erlang programmers rarely use if
. Using case
often gives more natural and concise code. Your example could be written as:
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).
With this code you have several issues:
lists:foreach/2
requires fun with arity one as first argument, you
have with two. I guess you have ?ALL_METHODS macros defined similar
to this: -define(ALL_METHODS, [{method1, 1}, {method2, 2}, ...])
then you could fix it with wrapping fun's arguments in tuple: fun(Method, Value)
will be fun({Method, Value})
- With
whereis(ServerName) =/= undefined
you have possible race condition, when whereis(ServerName)
return pid()
at first, then process for some reason dies and on the next step it will be undefined
(but it is hard to say 100% sure without context).
- You do
method_to_servername(Method)
twice.
And about your question, guard functions in Erlang do allow only certain subset of functions.