Pattern matching with a guard clause

I have a function

 def getValue(a, b, c, d), do: {d}

and a second one:

 def getValue(a, b, b, d), do: {d}

I notice that if i pass (1,2,2,3) the first function is executed and returns 3. However if I wanted to enforce that each letter must be a different value would a guard clause such as a != b and b !=c and c != d be the idiomatic way to approach the filtering or is the best way moving the second function above the first ?

Thank you,

You can absolutely do both!

But many times people do arrange their functions so that guard clauses are not (or less) necessary, so if in your case, you can achieve the same by simply moving the functions around, Iā€™d say go for it :slight_smile:

1 Like

Please use code format for your code snippet, itā€™s going to help people to read your code.

About your question. I donā€™t think moving the second function clause as the first will solve your problem. It doesnā€™t guarantee the variable a or d will be different. You either make a guard clause as you proposed or you make the filtering inside the function body which I believe not what youā€™re looking for. I believe itā€™s fine doing guard clause that way as long as itā€™s idempotent which is enforced by BEAM anyway. But maybe another person more experienced than me can give a better answer. I hope this help.

Thanks and sorry I will use the code snippets in the future. And will try both :slight_smile:

Anytime :slight_smile:

Forgot to ask what to select to use ā€œcode formatā€ I see the icons available above where i type this message. Are you referring to the </> icon ?

Thanks,

As moderator I have taken the liberty to make your post more readable. When editing, you can see what I did, so youā€™ll be able to use the code blocks yourself from now on :slight_smile: .


If you want to enforce that all letters are different, then writing all ā€˜falseā€™ statements out as separate clauses would take quite a bit of work, as there are 4*3*2*1 = 24 function heads. So I would also go for this approach:

def get_value(a, b, c, d) when a != b and b != c and c != d, do: {d}
def get_value(a, b, c, d), do: # ... something else

Thanks for providing an example for formatting and also the recommendation of use the guard clause. I am still new to this language and was also wondering why the following fails

 [a, a, b, c, d, e, e] = [ {2} ,{2} ,{3}, {4}, {9}, {9}, {13}]

but this one works

 [a, a, b, c, d, e, f] = [{2}, {2} , {3}, {4}, {9} ,{9} ,{13} ]

I would have figured that the second one would have also failed but it allows d to have a 9 and e to have a nine.

Thank you,

1 Like

The first fails because youā€™re trying to bind {9} to e and also trying to bind {13} to e. e cannot be both 9 and 13, so it fails. In the second case, each variable is bound to only one value, so it works.

Ah yes thanks! I see what you mean now. My OOP background is killing me here :grinning:

Iā€™m confused what youā€™re saying, I assume heā€™s not trying to enforce a and d are different, just trying to enforce that ā€œbā€ and ā€œcā€ are different, hence b, b in the second definitionā€¦ if he moves that clause first, I just tested in IEx and it definitely will enforce they are the same value and will not hit the clause unless they are the sameā€¦ or is that not what you meant?

edit: Oh, I see, I overlooked/misread the details of the guard clauses, my bad! I guess he did want to enforce a and d being different. I think conventions in math here help, where x and y could both happen to be 5, but x and another copy of x must always be the same value, whatever that value is.

Yes I was trying to enforce that B and C were different. As I am just learning how the pattern matching works I was under the impression that each letter would be different but I understand why that is not the case but rather I could not have two separate values assigned to the same letter.

I love the way pattern matching works in this language with function signatures :slight_smile:

Hahaha. No worries. At first I though so since the code snipped only stating duplicate b.

Pattern matching in Elixir is cool. You can also pattern match on string, list, keywords, map, struct, and other built in data structures if thatā€™s not all.

Coming from .NET and F# I really wish F# allowed the Pattern Matching in the signature as opposed to having to do match (x) with etcā€¦

Its a nice progress. I think this functional language is boss. Right now Iā€™ve only been able to use Elixir for side projects but eventually I want to bring it into the work environment :slight_smile:

1 Like

It should for a single argument at a time in the function definition by using the function keyword that it got from OCaml.

Correct but not multiple guard clauses elixir wins. I still like F# but right now this is my choice for breakfast, lunch and dinner :grinning:

True true, in OCaml/F# you have to pack them together if you want to match on multiple at once, either by passing in a tuple or doing it directly like:

let some_func a b c = match a, b, c with
| 42, "hello", 6.28 -> 42
| 42, blah, bloop when bloop >= 0.0 -> 16
| a, b, c -> 0

EDIT: This also happens to be how the EVM/BEAM translates its multiple heads internally, they just go to a single function that goes to a case statement where the heads are in the case statement. :wink: