Check out our new series - Moving to Elixir

×

#33: Elixir Control Flow

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.