Subscribe to access all episodes. View plans →
Published January 22, 2018
Elixir 1.5.3
In this episode we’ll take a look at control flow in Elixir.
Specifically we’ll look at three different control structures: if/else, case statements, and conditionals.
Let’s get started.
Here we have a module Greeter
with a single function greet
that returns the string "Hello"
.
Now let’s update our function to only return "Hello"
if the language is English.
First we’ll add the parameter lang
to our function.
And then let’s add an if statement. So that if our lang
variable is the abbreviation for English - "en"
- "Hello"
is returned.
greeter.exs
defmodule Greeter do
def greet(lang) do
if lang == "en" do
"Hello"
end
end
end
Let’s try it out.
We’ll go to the console and run iex
with our file greeter.exs
. And if we run Greeter.greet("en")
- it returns "Hello"
.
Now let’s try it again only this time we’ll run it with another language like French.
And nil
is returned.
> Greeter.greet("en")
"Hello"
> Greeter.greet("fr")
nil
Let’s go back to our module and add an else statement to print "Bonjour"
if the language isn’t English. (Skip to last part of recording - I went back and re-did a better take - I think - at the end.)
Now while this will work as-is. We can shorten it and collapse it to one line.
greeter.exs
defmodule Greeter do
def greet(lang) do
if lang == "en", do: "Hello", else: "Bonjour"
end
end
Then let’s go back and reload our module.
And if we use "en"
it still returns "Hello"
Then if we use "fr"
it now returns "Bonjour"
.
While this is great, what happens if we try another language.
Let’s try it with the abbreviation for Spanish.
And "Bonjour"
is returned, which is not what we wanted.
> r(Greeter)
{:reloaded, Greeter, [Greeter]}
> Greeter.greet("en")
"Hello"
> Greeter.greet("fr")
"Bonjour"
> Greeter.greet("es")
"Bonjour"
In order to add more branches of logic, let’s reach for another control flow structure - the case statement.
The case statement let’s us match against many different values for our variable lang
.
We’ll define our case statement with the variable we want to match against.
And let’s match against English, Frech, and Spanish.
greeter.exs
defmodule Greeter do
def greet(lang) do
case lang do
"eng" -> "Hello"
"fr" -> "Bonjour"
"es" -> "Hola"
end
end
end
Then back in our iex
session we’ll reload the module.
And let’s try it out.
English returns “Hello”.
And Spanish returns “Hola”.
Then if we try a language that we haven’t defined, we get an error: no case clause matching
.
Let’s go back to our module.
And let’s add an underscore to catch all other cases.
greeter.exs
defmodule Greeter do
def greet(lang) do
case lang do
"eng" -> "Hello"
"fr" -> "Bonjour"
"es" -> "Hola"
_ -> "We don't have a greeting for that."
end
end
end
In iex
we’ll reload our module.
And let’s try it again with a language we didn’t define a clause for.
And great, our catch-all message was triggered.
Now case statements are great for matching on the value of our variable, but what if we need to match against expressions that return true
?
For that we can use another control flow structure: cond
(condition).
Let’s go back to our module. And we’ll define our conditions for when English is true, French, and Spanish.
Now if we want to define a final expression to catch any other conditions we’ll just use true
and then add a message.
greeter.exs
defmodule Greeter do
def greet(lang) do
cond do
lang == "en" ->
"Hello"
lang == "fr" ->
"Bonjour"
lang == "es" ->
"Hola"
true ->
"We don't have a greeting for that."
end
end
Then we’ll go back it iex
on last time and reload our module.
And if we try our function with different languages, we still get the correct greetings.
Nathan
7 years agoGood video, but…
I initially misunderstood your sentence below to mean that
case
couldn’t compare againsttrue
, and that made no sense.Perhaps a clearer explanation would be:
And, provide an example that actually couldn’t be written with
case
. Your current example forcond
would work fine forcase
, so it really doesn’t illustrate the difference between the two.Alekx
7 years agoHey Nathan, those are good points. Thanks for the feedback.