hst337
November 9, 2022, 11:19pm
1
Why map update syntax does not work in guards?
1> case [1, 2, 3] of
1> X when #{x => 1}#{x => 2} =:= #{x => 2} -> X
1> end.
[1,2,3]
and
iex> case [1, 2, 3] do
...> x when %{%{x: 1} | x: 2} == %{x: 2} -> x
...> end
Should I submit it as a bug, or is it intended?
2 Likes
I don’t think that is supported, there’s still a few things in guards that haven’t made it over in the parser, for example I believe map_get is not supported.
hst337
November 9, 2022, 11:52pm
3
map_get
is supported because it is a function, not an expression
iex(1)> case %{x: 1} do
...(1)> x when :erlang.map_get(:x, x) == 1 -> x
...(1)> end
%{x: 1}
IIRC Erlang supports only updates of literal values and I am not sure there is a need for it in Elixir because you could merge them at compile time if you need similar behavior.
3 Likes
What would be the use case for this? Isn’t the above guard checking whether 2 == 2?
2 Likes
hst337
November 10, 2022, 3:06pm
6
What do you mean by literal values?
1> X = x.
2> M = #{x => 1}.
3> case 1 of
3> Y when M#{X => Y} =:= #{x => 1} -> ok
3> end.
ok
1 Like
TIL! That’s news to me.
It is something we could support then. Is there any use case for it though?
1 Like
hst337
November 10, 2022, 6:08pm
8
I thought about something like
defguard is_same_struct?(left, right) when %{left | meta: nil} == %{right | meta: nil}
Or
defguard equal_request?(left, right) when %{left | timestamp: nil} == %{right | timestamp: nil}
4 Likes
hst337
November 10, 2022, 6:15pm
9
Or even more general and useful example
defguard field_polymorphic?(left_struct, right_struct) when %{left_struct | __struct__: nil} == %{right_struct | __struct__: nil}
1 Like
Hrm… good question. I wonder if that’s indeed the fastest way to compare maps in such scenarios?
hst337
November 10, 2022, 11:16pm
11
How would you compare them the other way? Key-by-key using :maps.iterator
?
For a small, known map, I would get the values directly and compare them.
1 Like
hst337
November 11, 2022, 8:39pm
13
This works only if you know all the keys by name.
1 Like