Difference between pattern matching and equality operator?

Hi,
This is my first post with the forum. I just started learning Elixir this week. I’ve been going through Dave Thomas’ Elixir for Programmer’s Course. I found that I wasn’t grasping certain things (the title of this post being one of them). Dave mentions how powerful pattern matching can be, but I’m not sure I understand why… It seems that pattern matching is essentially and equality operator ( == ). Is it? If not, how are they different? What makes pattern matching so powerful compared to languages without it? Thanks in advance!

For one the equality operator has a boolean result - the result of a pattern match is the value that was successfully matched or a match error.

Furthermore a successful pattern match is capable of destructuring the matched value - essentially binding the matched destructured values to the specified names.

Have you looked at Pattern Matching yet?

Pattern matching is important for case expressions and multi-clause functions

Function declarations also support guards and multiple clauses.

Guards can be used to impose additional conditions on the pattern match.

Even anonymous functions can have multiple clauses.

Pattern matching is a conditional construct that can help to manage the Pyramid of Doom/Arrow Code (with/1 is also often used in that capacity).

1 Like

Thank you for the quick reply! Your response has been very helpful!

I have looked over the documentation in regards to Pattern Matching as well as other resources. I suppose there is one thing that you said that isn’t quite clear to me yet (though it is becoming more clear). What do you mean (as well as the documentation) when you say destructure? Would you mind sharing an example?

Thanks again.

destructure is to pick out a piece of a data that you want from an existing data-structure such as a tuple, list or a map.

Lets create a map, and then bind ‘a’ to variable ‘x’ but only if ‘b’ == 2.

ex(1)> m = %{a: 1, b: 2, c: 3, d: 4}
%{a: 1, b: 2, c: 3, d: 4}
iex(2)> %{a: x, b: 2} = m
%{a: 1, b: 2, c: 3, d: 4}
iex(3)> x
1
iex(4)> %{a: y, b: 3} = m
** (MatchError) no match of right hand side value: %{a: 1, b: 2, c: 3, d: 4}   

Or pick the coordinates of a a simple tuple representing a point:

iex(1)> point = {:point, 1.5, 3.9}
{:point, 1.5, 3.9}
iex(2)> {:point, x, y} = point
{:point, 1.5, 3.9}
iex(3)> x
1.5
iex(4)> y
3.9
iex(5)>
1 Like

It is when You decompose something into smaller pieces.

for example

%{a: a, b: b} = %{a: 1, b: 2}

-> a is pattern matched with 1
-> b is pattern matched with 2

In javascript, it is called destructuring and would be

const value = {a: 1, b:2}
const {a, b} = value

1 Like

Thats a natural tendency. Very tricky since it seems it would be. In addition to the particular explanations you have gotten I’d make a general suggestion learning Elixir. Don’t expect a 100% equivalence to other languages (mainly if this is your first functional language). That put me off too since I am used to getting a new language quickly due to just relating the new language to the OOP languages I already knew. For myself I got pattern matching when I just considered it something new without trying to relate it to anything.

This person had your same impression

Heres another explanation

1 Like

To expand on this: destructuring assignment was an ECMAScript 2015 addition (see also Exploring JS: 10. Destructuring).

However it is important to note that

  • while pattern matching is used for destructuring
  • destructuring is not pattern matching

If the data doesn’t even have the “right shape” then a pattern match will fail (i.e. result in a match error). When in ES2015 the data doesn’t have the “right shape” the respective destructuring variables will simply be undefined

> const x = {a: 1, b: 2}
> console.log(a)
    Uncaught ReferenceError: a is not defined
        at <anonymous>:1:13
    (anonymous) @ VM480:1
> console.log(b)
    Uncaught ReferenceError: b is not defined
        at <anonymous>:1:13
    (anonymous) @ VM484:1
> const {a,b} = x
> console.log(a)
    1
> console.log(b)
    2
> console.log(c)
    Uncaught ReferenceError: c is not defined
        at <anonymous>:1:13
    (anonymous) @ VM530:1
> console.log(d)
    Uncaught ReferenceError: d is not defined
        at <anonymous>:1:13
    (anonymous) @ VM534:1
> const y = 3
> const {c,d} = y
> console.log(c)
    undefined
> console.log(d)
    undefined
>

This is the basis for Rich Hickey’s observation that

Pattern matching is a conditional construct and destructuring isn’t.

3 Likes

Thank you for all your comments and sharing of links. I am starting to understand better now. Your help is much appreciated!

1 Like