0, 1, 1, 2, 3, 5, 8, 13, 21...
3. Numbers
In Elixir, numbers are divided into two categories: integers and floats. Integers are whole numbers, the type you count on your hand: 3
, 0
, 1123
, etc.
Floats are numbers that can contain fractional parts, like 1.333333
or 0.01
. They are called "floats" because of the way they are represented
in memory. You don’t need to know that, but if you want to learn more you can read up on floatingpoint arithmetic.
To be honest, I had to look it up myself while writing this very paragraph!
In this chapter we will go over the basics of numbers and floats, along with introducing some other pattern matching mechanisms that Elixir has, among other things. Let’s dive in!
3.1. Fibonacci
The Fibonacci numbers are a famous set of numbers that form a sequence, where each number is the sum of the two preceding ones. You may have seen them before:
It is represented mathematically like so:
F₀ = 0
F₁ = 1
Fₙ = F₀ + F₁
Which means 2
in the sequence above is the 3rd Fibonacci number, and 0
is the 0th (zeroth).
Let’s write a program that can compute any Fibonacci number for us.
We can give it a number, n
, like 6
and it will return the corresponding Fibonacci number, 8
.
3.1.1. Function pattern matching
Let’s start with the test:
Code.require_file("fibonacci.ex")
ExUnit.start()
defmodule FibonacciTest do
use ExUnit.Case
test "calculates 0th number" do
assert Fibonacci.calculate(0) == 0
end
test "calculates 1st number" do
assert Fibonacci.calculate(1) == 1
end
end
Here we are just testing the 0th and 1st number, but we’ll add more later. Run the test to ensure that it fails, as we would expect:
** (Code.LoadError) could not load [...]fibonacci.ex
(elixir 1.12.2) lib/code.ex:1807: Code.find_file/2
(elixir 1.12.2) lib/code.ex:1254: Code.require_file/2
fibonacci_test.exs:1: (file)
(elixir 1.12.2) lib/code.ex:1261: Code.require_file/2
Our fibonacci.ex
file doesn’t exist yet, so our test is failing to run.
Note that "failing to run" is not the same as "running, then failing". In this case, our tests are not actually running!
Let’s create fibonacci.ex
and add the minimal code needed to make our fibonacci_test.exs
actually run:
defmodule Fibonacci do
end
With that in place, we can see the familiar ExUnit
output:
$ elixir fibonacci_test.exs
warning: Fibonacci.calculate/1 is undefined or private
Found at 2 locations:
fibonacci_test.exs:8: FibonacciTest."test calculates 0th number"/1
fibonacci_test.exs:12: FibonacciTest."test calculates 1st number"/1
1) test calculates 0th number (FibonacciTest)
fibonacci_test.exs:7
** (UndefinedFunctionError) function Fibonacci.calculate/1 is undefined or private
code: assert Fibonacci.calculate(0) == 0
stacktrace:
Fibonacci.calculate(0)
fibonacci_test.exs:8: (test)
2) test calculates 1st number (FibonacciTest)
fibonacci_test.exs:11
** (UndefinedFunctionError) function Fibonacci.calculate/1 is undefined or private
code: assert Fibonacci.calculate(1) == 1
stacktrace:
Fibonacci.calculate(1)
fibonacci_test.exs:12: (test)
Finished in 0.1 seconds (0.1s on load, 0.00s async, 0.01s sync)
2 tests, 2 failures
Randomized with seed 362639
Now let’s write the code needed to make it pass:
defmodule Fibonacci do
def calculate(0) do
0
end
def calculate(1) do
1
end
end
In Elixir, we can also do "matching" within the function definition itself, which is what we are doing here.
When you call calculate/1
with a parameter, Elixir will find the function definition that "matches" the parameter you provide.
This works similarly to how case
works, which we saw in action in the previous chapter.
So when we call calculate/1
with the value of 1
, as we do in our test, Elixir will first look at def calculate(0)
,
see that 1 != 0
, and then look at the next definition. The next definition, def calculate(1)
does match, and Elixir
will in turn execute the do
/end
block associated with that definition.
Since functions are dispatched in this "matching" manner, we can define the same function multiple times.
That is, in addition to defining functions with different arities, like greet/0
and greet/1
, we can also
define multiple functions with the same arity, like we do here with calculate/1
.
Functions, just like case
, are matched in order from the first definition in the module to the last, too.
If you haven’t already, run the tests to verify that your code passes:
$ elixir fibonacci_test.exs
..
Finished in 0.04 seconds (0.03s on load, 0.00s async, 0.01s sync)
2 tests, 0 failures
Randomized with seed 601683
3.1.2. Recursion
Let’s define the rest of the behavior we want from our calculate/1
function with some more tests:
Code.require_file("fibonacci.ex")
ExUnit.start()
defmodule FibonacciTest do
use ExUnit.Case
test "calculates 0th number" do
assert Fibonacci.calculate(0) == 0
end
test "calculates 1st number" do
assert Fibonacci.calculate(1) == 1
end
test "calculate 8th number" do
assert Fibonacci.calculate(8) == 21
end
end
Here we add a test for the 8th Fibonacci number, which I got from the sequence at the top of this chapter. With that added, let’s run our tests:
$ elixir fibonacci_test.exs
..
1) test calculate 8th number (FibonacciTest)
fibonacci_test.exs:15
** (FunctionClauseError) no function clause matching in Fibonacci.calculate/1
The following arguments were given to Fibonacci.calculate/1:
# 1
8
code: assert Fibonacci.calculate(8) == 21
stacktrace:
fibonacci.ex:2: Fibonacci.calculate/1
fibonacci_test.exs:16: (test)
Finished in 0.09 seconds (0.07s on load, 0.00s async, 0.02s sync)
3 tests, 1 failure
Randomized with seed 30951
Our test fails with a FunctionClauseError
. Though we do have a calculate/1
function
defined, none of its function clauses match the parameter we passed in. This is because
our current calculate/1
only has function clauses for 0
and 1
.
Let’s add a third function clause that handles the case for the third or later Fibonacci number. By referencing the formula in Listing 2, we come up with this:
defmodule Fibonacci do
def calculate(0) do
0
end
def calculate(1) do
1
end
def calculate(n) do
calculate(n1) + calculate(n2)
end
end
Our code here looks almost exactly like the formula. If the parameter we get is 0 or 1, we return those respective values, otherwise we recursively compute the value by calculating the prior two Fibonacci numbers and adding them together.
Run the tests to verify the solution works.
3.1.3. Function clause guards
Our Fibonacci
module works great. However, there is one problem: other programmers
keep on calling it with strings instead of integers! They pass in "5"
instead of 5
.
They say calling it with these "numbers" results in an ArithmeticError
in our module.
Because the error comes from our module, they insist it is our code that has the bug
not theirs!
We did not really expect this sort of usage, so we should guard against it. Our code should be defensive against "bad" inputs, to make it clear to other programmers using our module that the issue is not in our module, but rather in how they are using our module.
Instead of having our code raise an ArithmeticError
, we should raise an error that indicates to the programmer that our function
is not meant to be used in the way they are using it. That it doesn’t accept the parameters
that are passed in.
What sort of error should we raise? How about the FunctionClauseError
that we encountered
earlier in Listing 7, when we tried to call calculate/1
with a number
before we defined that functionality. That makes it clear that our function has no clause
for their parameter, which is much more clear!
In Elixir, we can assert an error is raised with the handy assert_raise/2
function.
Let’s add a test, using that:
defmodule Fibonacci do
def calculate(0) do
0
end
def calculate(1) do
1
end
def calculate(n) do
calculate(n1) + calculate(n2)
end
end
assert_raise/2
takes in an exception and a function to run that should raise that exception when executed.
In Elixir, in addition to defining a function in a module with def
, we can also define a function
within a block with the fn >
shorthand. This is known as an anonymous function, because it has no
name. We will cover anonymous functions in much more detail in a later chapter.
Let’s run our test:
$ elixir fibonacci_test.exs
..
1) test handles strings (FibonacciTest)
fibonacci_test.exs:19
Expected exception FunctionClauseError but got ArithmeticError (bad argument in arithmetic expression)
code: assert_raise FunctionClauseError, fn >
stacktrace:
fibonacci.ex:11: Fibonacci.calculate/1
fibonacci_test.exs:20: (test)
.
Finished in 0.09 seconds (0.06s on load, 0.00s async, 0.03s sync)
4 tests, 1 failure
Randomized with seed 805110
Great! Here we have added a test that reproduces what those other programmers were telling us,
that our code is raising an ArithmeticError
. We see that the test fails because our asset_raise
was expecting a FunctionClauseError
.
In Elixir, we can guard against bad inputs with Guards. Essentially, in a function clause, we can add a guard that tells Elixir what sort of things the function is willing to accept.
There are many types of guards. For us, we want to check that the parameter is a number.
So we can use the is_integer
one.
Add it to your last function clause like so:
defmodule Fibonacci do
def calculate(0) do
0
end
def calculate(1) do
1
end
def calculate(n) when is_integer(n) do
calculate(n1) + calculate(n2)
end
end
And run the tests again. They all pass! Now next time someone tries to call our
calculate/1
function with a string, they will get a FunctionClauseError
, making
clear to them that our function does not match their parameters.
3.1.4. Just , do:
it
This pattern of having a variety of short function definitions to implement
a given function is quite common in Elixir. It is not unusual to have even up to
ten function clauses for a single function. This has the benefit of skimming
the various cases the function could handle quite easy. However, it does often
feel more verbose than just having that matching logic within a single function
via case
or similar.
Luckily, in addition to the traditional do
/end
deliminated function body block,
Elixir also has a "shorthand" way of defining the function body by using just , do:
alone.
Update your fibonacci.ex
file as follows, to see it in action:
defmodule Fibonacci do
def calculate(0), do: 0
def calculate(1), do: 1
def calculate(n) when is_integer(n), do: calculate(n1) + calculate(n2)
end
This shorthand style is only used when the body of the function only has
a single line of code. As you see, it compresses the number of lines a function
takes up from three to one, in our case. Note that for this , do:
style, we have
a comma after the closing parenthesis. In the do
/end
style, there is no such
comma.
After refactoring, run the tests again to make sure your refactor did not introduce any regressions.
3.2. FizzBuzz
One of the most common interview questions out there is implementing Fizz buzz. It’s a simple game where we print a range of numbers with the following rules:

If the number is divisible by 3, print
"Fizz"

If the number is divisible by 5, print
"Buzz"

If the number is divisible by 3 and 5, print
"FizzBuzz"

Otherwise, print just the number.
Actually, one of my first programming jobs I got in college had this question in the interview. I think that was the first time I ever saw it.
Anyway, let’s implement this in Elixir!
3.2.1. Remainders with rem
As always, start with a test. Create a new file, fizz_buzz_test.exs
, and let’s translate the requirements above into code:
Code.require_file("fizz_buzz.ex")
ExUnit.start()
defmodule FizzBuzzTest do
use ExUnit.Case
test "handles divisible by 3" do
assert FizzBuzz.solve(3) == "Fizz"
end
test "handles divisible 5" do
assert FizzBuzz.solve(5) == "Buzz"
end
test "handles divisible by 3 and 5" do
assert FizzBuzz.solve(15) == "FizzBuzz"
end
test "handles not divisible" do
assert FizzBuzz.solve(7) == 7
end
end
Additionally, create a fizz_buzz.ex
file that simply defines our module:
defmodule FizzBuz do
end
And let’s run our tests to verify they are failing, as we would expect:
$ elixir fizz_buzz_test.exs
warning: FizzBuzz.solve/1 is undefined or private
Found at 4 locations:
fizz_buzz_test.exs:8: FizzBuzzTest."test handles divisible by 3"/1
fizz_buzz_test.exs:12: FizzBuzzTest."test handles divisible 5"/1
fizz_buzz_test.exs:16: FizzBuzzTest."test handles divisible by 3 and 5"/1
fizz_buzz_test.exs:20: FizzBuzzTest."test handles not divisible"/1
1) test handles not divisible (FizzBuzzTest)
fizz_buzz_test.exs:19
** (UndefinedFunctionError) function FizzBuzz.solve/1 is undefined or private
code: assert FizzBuzz.solve(7) == 7
stacktrace:
FizzBuzz.solve(7)
fizz_buzz_test.exs:20: (test)
2) test handles divisible by 3 (FizzBuzzTest)
fizz_buzz_test.exs:7
** (UndefinedFunctionError) function FizzBuzz.solve/1 is undefined or private
code: assert FizzBuzz.solve(3) == "Fizz"
stacktrace:
FizzBuzz.solve(3)
fizz_buzz_test.exs:8: (test)
3) test handles divisible by 3 and 5 (FizzBuzzTest)
fizz_buzz_test.exs:15
** (UndefinedFunctionError) function FizzBuzz.solve/1 is undefined or private
code: assert FizzBuzz.solve(15) == "FizzBuzz"
stacktrace:
FizzBuzz.solve(15)
fizz_buzz_test.exs:16: (test)
4) test handles divisible 5 (FizzBuzzTest)
fizz_buzz_test.exs:11
** (UndefinedFunctionError) function FizzBuzz.solve/1 is undefined or private
code: assert FizzBuzz.solve(5) == "Buzz"
stacktrace:
FizzBuzz.solve(5)
fizz_buzz_test.exs:12: (test)
Finished in 0.1 seconds (0.1s on load, 0.00s async, 0.00s sync)
4 tests, 4 failures
Randomized with seed 702309
We haven’t implemented solve/1
yet, so these UndefinedFunctionError
failures are exactly
what we would expect.
In Elixir, we can find whether one number is divisible by another with the builtin rem/2
function.
If you have worked with other programming languages, this is the equivalent of the module operator, %
. It simply returns the remainder of the division operation.
For example rem(10,2) == 0
and rem(10,3) == 1
.
Let’s try implementing this with guards and case
:
defmodule FizzBuzz do
def solve(num) do
case num do
num when rem(num, 3) == 0 and rem(num, 5) == 0 >
"FizzBuzz"
num when rem(num, 3) == 0 >
"Fizz"
num when rem(num, 5) == 0 >
"Buzz"
not_divisible >
not_divisible
end
end
end
The same guards we used on our function clauses earlier can also be used on case clauses.
Here we also use the and
operator to combine two guards for our first clause, to
ensure it is divisible by both 3 and 5.
You may be asking: why don’t we use function guard clauses instead, like we did with Fibonacci? There is no particular reason, and using function guard clauses would work just as well. In fact, that is one of the exercises at the end of this chapter.
Run the tests again to verify everything passes.
3.2.2. Conditions with cond
In addition to case
and if
/else
, Elixir has the cond
flow control structure.
To review, if
evaluates a single expression, and runs the associated block if that
expression evaluates to true, otherwise evaluating the else
block, if it exists.
case
uses pattern matching, evaluating the block of code associated with the matching clause.
cond
is similar to else if
in other programming languages. Instead of working on
matching, it works in the same way if
does: by evaluating expressions one by one
and running the block of code associated with the first expression that evaluates
to true.
Let’s refactor our code to use cond
, to explore further:
defmodule FizzBuzz do
def solve(num) do
cond do
rem(num, 3) == 0 and rem(num, 5) == 0 >
"FizzBuzz"
rem(num, 3) == 0 >
"Fizz"
rem(num, 5) == 0 >
"Buzz"
true >
num
end
end
end
As you can see, cond
is a bit more succinct in this case. As mentioned, cond
is used
when we have a variety of expressions to evaluate. It is typically used less frequently
that case
and pattern matching in general.
Our last condition is simply true
, which is always true, so serves as our final
catchall. If a cond
construct has no expression that evaluates to true, then
a CondClauseError
will be raised.
Run the tests to ensure that our little refactor did not introduce any regression, and that the tests still pass.
3.3. Whirlwind operator tour, with tests
In a chapter called "Numbers", we’ve only used the rem
and +
operators so far! Let’s
fix that by doing a bit of a whirlwind tour of all the operators we typically use with
numbers. We won’t be creating a module this time, but will instead be expanding and
reinforcing our understanding by creating a series of tests that explore each of them.
Create a file called numbers_test.exs
, where we will add our tests:
ExUnit.start()
defmodule NumbersTest do
use ExUnit.Case
end
Let’s get started!
3.3.1. Number operators
In addition to the +
operator, Elixir of course also has the 
operator. It works
just as you would expect it to:
test " operator" do
assert 1  5 == 4
end
Related to the rem
operator is the div
operator. div
is the integer division operator.
It only returns the result rounded towards zero.
test "div operator" do
assert div(10, 2) == 5
assert div(11, 2) == 5
assert div(12, 2) == 6
end
You may want a float result instead. For that you can use the /
operator.
test "/ operator" do
assert 10 / 2 == 5.0
assert 11 / 2 == 5.5
assert 12 / 2 == 6.0
end
When any sort of operation uses both an integer and a float, the result is usually a float.
We can show this by way of the *
operator, which multiplies.
test "* operator" do
assert 1.0 * 5 == 5.0
assert 50 * 20 == 1000
assert 2.2 * 4.1 == 9.02
end
3.3.2. Comparison operators
All of our tests already use at least one comparison operator: ==
! It compares
the value between the two operands, as we know. It isn’t very strict when comparing
between floats and integers though.
test "== operator" do
assert 1.0 == 1
assert 1.0000000000000001 == 1
end
The ===
operator is more strict when comparing between floats and integers.
test "=== operator" do
refute 1.0 === 1
refute 1.0000000000000001 === 1
assert 1 === 1
assert 1.01 === 1.01
end
Here we use the refute/1
macro. It’s the opposite of assert
, and only succeeds if the operation does not return a truthy value.
We also have the !=
and !==
operators, which test that two values do not match.
The !==
operator, like the ===
operator, is more strict in its comparison.
test "!= and !== operators" do
refute 1.0 != 1
assert 1.0 !== 1
end
Of special interest to numbers is determining whether a number is smaller or larger.
We can do this with the <
and >
operators, respectively.
test "> and < operators" do
assert 1 < 2
assert 1 < 1.00001
assert 9001 > 9000
assert 55 > 60
end
We can tack on a =
to the end of each to also return true if the values are equal.
test ">= and <= operators" do
assert 1 >= 1.0
assert 1 <= 1.00001
end
Whew! And with that, we know all the operators we need to know for numbers.
3.4. Conclusion
In this chapter we got to explore more of the basics. You are now equipped to
pass two of the most common interview questions: Fibonacci and FizzBuzz! Next up
is learning about two of the more unique parts of Elixir: tuples and the =
match
operator, among many other things. Onward!
3.4.1. What we learned in this chapter

Function definitions can utilize pattern matching, just like
case
. 
Guards are used for making our match more specific. They can be added to match clauses, like function definitions and
case
clauses. 
We can use the shorthand
, do:
syntax to make our function bodies more concise. 
rem/2
can be used to calculate the remainder of a division operation. 
cond
can be used to evaluate a series of expressions to determine what block of code to execute. It is similar to "elseif" chains in other programming languages. 
A whirlwind tour of all the other operators in Elixir!
3.4.2. Exercises

Calling
Fibonacci.calculate/1
with a negative number like1
results in the program hitting an infinite loop. Add a functional guard clause to guard against negative numbers. Hint: you can use comparison operators in guard clauses. 
Convert
FizzBuzz.solve/1
to use function clause guard matching instead ofcond
. 
Convert
Fibonacci.calculate/1
to usecond
instead of function clause guard matching. 
Update
FizzBuzz
to print"aww"
if a number is not divisible by 3 or 5, instead of printing the number. As always, update the test, first! 
FizzBuzz.solve/1
currently does not guard against nonnumber parameters. Add a guard clause doing just that.