Function Calls and Pattern Matching

In the previous chapter we covered how anonymous functions use pattern matching to bind their parameter list to the passed arguments. The same is true of named functions. The difference is that we write the function multiple times, each time with its own parameter list and body. Although this looks like multiple function definitions, purists will tell you it’s multiple clauses of the same definition (and they’d be right).

When you call a named function, Elixir tries to match your arguments with the parameter list of the first definition (clause). If it cannot match them, it tries the next definition of the same function (remember, this must have the same arity) and checks to see if it matches. It continues until it runs out of candidates.

Let’s play with this. The factorial of n, written n!, is the product of all numbers from 1 to n. 0! is defined to be 1.

Another way of expressing this is to say

This is a specification of the concept of factorial, but it is also close to an Elixir implementation:

mm/factorial1.exs
 defmodule​ Factorial ​do
 def​ of(0), ​do​: 1
 def​ of(n), ​do​: n * of(n-1)
 end

Here we have two definitions of the same function. If we call Factorial.of(2), Elixir matches the 2 against the first function’s parameter, 0. This fails, so it tries the second definition, which succeeds when Elixir binds 2 to n. It then evaluates the body of this function, which calls Factorial.of(1). The same process applies, and the second definition is run. This, in turn, calls Factorial.of(0), which is matched by the first function definition. This function returns 1 and the recursion ends. Elixir now unwinds the stack, performing all the multiplications, and returns the answer. This factorial implementation works, but it could be significantly improved. We’ll do that improvement when we look at tail recursion.

Let’s play with this code:

 iex>​ c ​"​​factorial1.exs"
 [Factorial]
 iex>​ Factorial.of(3)
 6
 iex>​ Factorial.of(7)
 5040
 iex>​ Factorial.of(10)
 3628800
 iex>​ Factorial.of(1000)
 40238726007709377354370243392300398571937486421071463254379991042993851239862
 90205920442084869694048004799886101971960586316668729948085589013238296699445
 ...
 00624271243416909004153690105933983835777939410970027753472000000000000000000
 00000000000000000000000000000000000000000000000000000000000000000000000000000
 00000000000000000000000000000000000000000000000000000000000000000000000000000
 00000000000000000000000000000000000000000000000000000000000000000000000000000

This pattern of design and coding is very common in Elixir (and almost all functional languages). First look for the simplest possible case, one that has a definite answer. This will be the anchor. Then look for a recursive solution that will end up calling the anchor case.

Here are a couple of examples:

Sum of the first n numbers

Length of a list

One point worth stressing: the order of these clauses can make a difference when you translate them into code. Elixir tries functions from the top down, executing the first match. So the following code will not work:

mm/factorial1-bad.exs
 defmodule​ BadFactorial ​do
 def​ of(n), ​do​: n * of(n-1)
 def​ of(0), ​do​: 1
 end

The first function definition will always match and the second will never be called. But Elixir has you covered—when you try to compile this, you’ll get a warning:

 iex>​ c ​"​​factorial1-bad.exs"
 .../factorial1-bad.ex:3: this clause cannot match because a previous clause at
  line 2 always matches

One more thing: when you have multiple implementations of the same function, they should be adjacent in the source file.