# Would somebody please explain the said lines in this test?

OK, that point is clear now, why doesn’t it work like the following?

``````assert %Product{} == p1
assert %Product{} == p2``````

because `%Product{}` and `%Product{name: "Tomato"}` are not equal. Remember `%Product{}` has default `name: nil`. By doing

``````%Product{} = %Product{name: "Tomato"}
``````

you check that the minimum matches. In this case both are `%Product{}`. You don’t check for equality. You check for common attributes.

Here are more iex examples

``````iex(14)> %{name: "John"} = %{name: "John", age: 14000}
%{age: 14000, name: "John"}
iex(15)> %{name: "John", age: 3} = %{name: "John", age: 14000}
** (MatchError) no match of right hand side value: %{age: 14000, name: "John"}

iex(15)> %{} = %{name: "John", age: 14000}
%{age: 14000, name: "John"}
iex(16)> %{name: "John"} == %{name: "John", age: 14000}
false
iex(17)> %{} == %{name: "John", age: 14000}
false
iex(18)>
``````
3 Likes

Double equals tests equality.

``````%Product{} = p1
``````

…is “does whatever is in p1 fit the shape of a Product struct?”

``````%Product{} == p1
``````

…is “is the empty Product struct exactly equal to whatever’s stored in p1?”

`==` is reversible, like the equals sign you remember from algebra class.

1 Like

Thank You @chulkilee @sergio @alexgaribay @yurko @voger @landric for replying!

Now it’s clear to me!

3 Likes

May I just add that this topic is fine example of why is an Elixir community great?

8 Likes

Another example, why Elixir core team and community are awesome!

1 Like
2 Likes

Great explanation! Thanks Voger.

2 Likes

Hi Shankar!

on the next page you combine

``````[p1, p2] = Catalog.list_products
assert %Product{} = p1
assert %Product{} = p2
``````

into

``````[p1 = %Product{}, p2 = %Product{}] = Catalog.list_products
``````

what if I write it like

``````[%Product{} = p1, %Product{} = p2] = Catalog.list_products
``````

instea of the above?

By the way it passes even if I make it like that.

The actual pattern match is:

``````[%Product{}, %Product{}] = Catalog.list_products
``````

i.e. the value of `Catalog.list_products` is a two element list, each of which is a `Product` struct. A successful match will simply evaluate to that two element list. To be clear:

• `[%Product{}, %Product{}]` is the pattern
• `Catalog.list_products` evaluates to the value being matched

So looking at

``````[%Product{} = p1, %Product{} = p2] = Catalog.list_products
``````

`p1` and `p2` are names inside a pattern. So at this point `=` is a mere a binding i.e. bind the name (e.g. `p1` or `p2`) to the sub-match (e.g. of `%Product{}`). And because it’s a mere binding (not a match) it can also be written as:

``````[p1 = %Product{}, p2 = %Product{}] = Catalog.list_products
``````

Furthermore:

``````iex(1)> a = 1
1
iex(2)> b = 2
2
iex(3)> [a,b] = [2,3]
[2, 3]
iex(4)> [^a,^b] = [3,4]
** (MatchError) no match of right hand side value: [3, 4]

iex(4)>
``````

i.e. if a name is used inside a pattern for the purpose of matching against the value that it is already bound to then that name/value has to be pinned.

``````Pattern = Value
``````

Generally speaking names inside a `Pattern` are bound while pinned names are matched. The top-level `=` has the `Pattern` to the left and the `Value` to the right. Any `=` inside `Pattern` is just a binding, not a pattern match.

1 Like

So you meant writing

`[p1 = %Product{}, p2 = %Product{}] = Catalog.list_product`

or

`[%Product{} = p1, %Product{} = p2] = Catalog.list_products`

in the said test, is the same, right?

Yes. It doesn’t matter.

1 Like

Thank you @peerreynders, thank you @voger!

Commenting on it 10 months later.

I think you wanted to say "Any `=` inside `Pattern` (i.e., `[p1 = %Product{}, p2 = %Product{}]` in this case) is just a binding pattern match, not pattern match binding.

note: Binding to me looks like assignment in non-functional languages like `a = 3` and pattern matching looks like checking for equality like if (`a == 3`) do this, else do that, (but not the strict equality), and in that sense I wrote the above comment.

With regards to `[p1 = %Product{}, p2 = %Product{}]`

• the pattern match is essentially `[%Product{}, %Product{}] = Catalog.list_products` i.e. a two element list where each element has to be a `Product` structure - otherwise the match will fail.
• after the match is successful the names `p1` and `p2` are bound to their values. `p1` is bound to the first element in the list and `p2` is bound to the second element in the list.

Now consider `[p1, p2] = Catalog.list_products`:

• the pattern match is essentially `[_, _] = Catalog.list_products` i.e. a two element list where each element can be any data type - otherwise the match will fail.
• after the match is successful the names `p1` and `p2` are bound to their values. `p1` is bound to the first element in the list and `p2` is bound to the second element in the list.

Finally `[^p1, ^p2] = Catalog.list_products`

• The match will only succeed if the first element of the list matches the current content of `p1` and the second element matches the current content of `p2` (and the list has exactly two elements).
1 Like

@pillaiindu
What @peerreynders wants to say is that.

`[p1 = %Product{}, p2 = %Product{}]` = `Catalog.list_products`

In the above pattern match, the main equal sign (in bold) is actually pattern matching (assigning) p1 and p2 to the elements resulted from the `list_products` function, and the first two equal signs (inside the LHS list) are merely checking if the p1 and p2 after the assignment are actually Product structs or not.

Edit: Or may be it’s saying, assign the two elements to p1 and p2 only if they were Product structs. But no matter which way you think about it, the effect is the same.

1 Like

Stripping it down to the bare essentials: `=` outside of a pattern is the match operator.
When you see `a = 3`

• the `_ = 3` match succeeds because `_` can be anything
• because the match succeeds `a` is bound to the value of the match: `3`
2 Likes

Thank you!

I think I already got that idea of how that pattern match worked 10 months ago, but I’m a bit confused about the terms. The term bind and pattern match.

There are two pattern matches in the code `[p1 = %Product{}, p2 = %Product{}] = Catalog.list_products`, which one he referred to in the above sentence.

Not the way I see it. There is one pattern - the list is part of the pattern. `p1` and `p2` want to be bound to specific sub-patterns if the overall match succeeds.

1 Like

You mean as he said,