Reputation: 8096
I am writing a function that will push a value to a list on a map if the key already exists, or init the key on the map with a new list if it does not already exist.
I tried making this part of the function guard expression but adding this guard expression to the function was illegal. I then tried making this an if but once again the guard expression was illegal. Finally I used a case which was fine.
I think the case is preferred here. But I'd like to understand why this guard expression is illegal. What does erlang see that makes it illegal?
If:
map_push(M, R, V) ->
if
maps:is_key(R, M) == true -> #{R := Row} = M, M#{R := [V|Row]};
maps:is_key(R, M) == false -> #{R => [V]}
end.
---
illegal guard expression
% 42| maps:is_key(R, M) == false -> #{R => [V]}
% | ^
Case:
map_push(M, R, V) ->
case maps:is_key(R, M) of
true -> #{R := Row} = M, M#{R := [V|Row]};
false -> #{R => [V]}
end.
Upvotes: 1
Views: 293
Reputation: 689
Well, actually it is not that complex if we carefully read the docs :)
Valid guard expressions are the following:
- Variables
- ...
So instead of calling the function maps:is_key
inside the if clause, you need to save the value of the function into a variable so that the evaluation of a guard expression can be guaranteed to be free of side effects
:
map_push(M, R, V) ->
IsKey = maps:is_key(R, M),
if
IsKey == true -> #{R := Row} = M, M#{R := [V|Row]};
IsKey == false -> #{R => [V]}
end.
Upvotes: 3
Reputation: 1782
Not just any function
is allowed inside Guard Expressions
.
For this particular one, however you can give this a try...
map_push(M, R, V) ->
if
is_map_key(R, M) == true -> #{R := Row} = M, M#{R := [V|Row]};
is_map_key(R, M) == false -> #{R => [V]}
end.
WYSIWYG
=> WHAT YOU SHOW IS WHAT YOU GET
Upvotes: 1