# Get a boolean whether two maps match or not

I would like to get a boolean if the maps match:

``````%{foo: :bar} =  %{foo: :bar, hello: :world}

%{foo: :bar} =  %{hello: :world}
``````

The problem is that

1. I can’t use “==” because both comparisons will return false;
2. The second assign will raise an error

How can I get a boolean so that the first assign that match will be true, and the latter false?

I think I can achieve that with `with`:

``````with %{foo: :bar} <- %{foo: :bar, hello: :world} do
true
else
_ -> false
end
``````

Is this the best way to achieve this? Is there a more concise way to write it?

The `Kernel.match?/2` function will help:

``````iex> match? %{foo: :bar}, %{foo: :bar, hello: :world}
true
iex> match? %{foo: :bar}, %{hello: :world}
false
``````
6 Likes
``````match?(%{too: bar}, input)
``````
2 Likes

I got an issue here:

`match?(Enum.into([foo: :bar], %{}), Enum.into([foo: :bar, hello: :world], %{}))`

** (CompileError) iex:1: cannot invoke remote function Enum.into/2 inside a match

Do you know why this error appears? It explains what I cannot do obviously, but doesn’t explain why.

`match?/2` is a macro, which basically expands into a `case/2` expression. So in the first argument its only allowed what would be allowed in a `case/2` on the left side of a match.

As far as I remember, `match/2` even allowed guards using `when` for the first argument.

``````iex(1)> match?(x when is_integer(x), 2)
true
iex(2)> match?(x when is_integer(x), :a)
false
``````
2 Likes

`match?/2` is actually a macro that compiles to a case expression. The parameters to `match?/2` are a `pattern` and an `expression`. So the first param needs to be a `pattern`.

3 Likes

In that case, I don’t know how to achieve what I want…

``````Enum.into(keyword_list1, %{})
Enum.into(keyword_list2, %{})
``````

How can I know if the first map matches with the second (something like map1 = map2)? I realize that even my `with` doesn’t work because the first part must be a pattern in a match, as you guys explained.

I converted the keyword lists into maps because I could easily check for matches (e.g. one keyword list is a subset of another); for example: %{foo: :bar} = %{foo: :bar, hello: :world}. It’s a characteristic I like about maps. I guess there’s no way to do it as I intended, and maybe it’s then not even worth to convert into a map.

You can use the pin operator (`^/1`) to achieve what you want:

``````left = Map.new(list1)
right = Map.new(list2)

match?(^left, right)
``````
1 Like

It doesn’t seem to work:

``````iex> map = %{foo: :bar}
%{foo: :bar}

iex> match?(^map, %{foo: :bar, hello: :world})
false

iex> match?(%{foo: :bar}, %{foo: :bar, hello: :world})
true
``````

Patterns aren‘t higher level constructs on the beam. You cannot construct patterns. You can just hardcode them.

3 Likes

Then I misremembered things about how maps match.

Perhaps you can use `MapSet` to check if one is the subset of another?

1 Like

If you already have keywords, why not work with them directly?

``````Keyword.equal?(kw1, Keyword.take(kw2, Keyword.keys(kw1)))
``````
3 Likes