3.12

Case Expression

Let’s say we have the weekdays being represented in numbers between 0 and 6 and we want to convert those numbers into strings (0 = Sunday, 1 = Monday, etc.). We can use an if expression to do that. Add the following function definition right above main in Playground.elm.

weekday dayInNumber =
    if dayInNumber == 0 then
        "Sunday"
    else if dayInNumber == 1 then
        "Monday"
    else if dayInNumber == 2 then
        "Tuesday"
    else if dayInNumber == 3 then
        "Wednesday"
    else if dayInNumber == 4 then
        "Thursday"
    else if dayInNumber == 5 then
        "Friday"
    else if dayInNumber == 6 then
        "Saturday"
    else
        "Unknown day"


main =
    ...

Now let’s render “Friday” on a browser by applying the weekday function from main.

main =
    weekday 5
        |> Html.text

If you refresh the page at http://localhost:8000/elm-examples/Playground.elm, you should see “Friday”. As it stands right now, the weekday function looks a bit superfluous. It does nothing more than a number comparison in each conditional branch. Can we express it more succinctly? Let’s try case expression.

weekday dayInNumber =
    case dayInNumber of
        0 ->
            "Sunday"

        1 ->
            "Monday"

        2 ->
            "Tuesday"

        3 ->
            "Wednesday"

        4 ->
            "Thursday"

        5 ->
            "Friday"

        6 ->
            "Saturday"

        _ ->
            "Unknown day"

Ah! Much better!

Case Expression Syntax

case works by matching an expression to a pattern. When a match is found, it evaluates the expression to the right of -> and returns whatever value is produced.

Pattern Matching
Pattern matching is the act of checking one or more inputs against a pre-defined pattern and seeing if they match. We will explore pattern matching in much more detail in chapter 4.

The expression after the keyword case can be anything from a simple value to a complex computation including function application. For example, if we want to generate a hashtag for each day, we can write another function that takes a string value returned by the weekday function and matches it against a hashtag. Add the following function definition right above main.

hashtag dayInNumber =
    case weekday dayInNumber of
        "Sunday" ->
            "#SinDay"

        "Monday" ->
            "#MondayBlues"

        "Tuesday" ->
            "#TakeMeBackTuesday"

        "Wednesday" ->
            "#HumpDay"

        "Thursday" ->
            "#ThrowbackThursday"

        "Friday" ->
            "#FlashbackFriday"

        "Saturday" ->
            "#Caturday"

        _ ->
            "#Whatever"


main =
    ...

Now apply the hashtag function instead of weekday in main.

main =
    hashtag 5
        |> Html.text

If you refresh the page at http://localhost:8000/elm-examples/Playground.elm, you should see “#FlashbackFriday”. You might be tempted to line each arrow (->) up when writing a case expression like this:

hashtag dayInNumber =
    case weekday dayInNumber of
        "Sunday"    -> "#SinDay"
        "Monday"    -> "#MondayBlues"
        "Tuesday"   -> "#TakeMeBackTuesday"
        "Wednesday" -> "#HumpDay"
        "Thursday"  -> "#ThrowbackThursday"
        "Friday"    -> "#FlashbackFriday"
        "Saturday"  -> "#Caturday"
        _           -> "#Whatever"

The Elm style guide tells us not to do that. Although this arrangement is easier on the eye, it takes aways the ease of modification. Let’s say we need to add another day with a long name to the list of patterns. Now we need to move all the arrows. But if we arrange the code as suggested by the style guide, then it becomes much easier to modify. Although elm-format automatically reformats our code to follow the style guide, I wanted to point it out here so that you understand why a case expression in Elm is formatted like that.

Catch All Pattern

Notice how we used _ in both examples above as the last pattern? Without it, Elm will throw an error. Go ahead and remove the line that contains _ from the weekday function and refresh the page at http://localhost:8000/elm-examples/Playground.elm. You should see the following error.

We have to account for every single value an expression can have. Since dayInNumber holds an integer whose range is quite big, it’s infeasible for us to list all those options in our code. The _ character works as a catch-all-pattern. Because of this, it’s important to place the most specific pattern at the top and the least specific at the bottom. For example, if we move _ at the top, the weekday function will always return “Unknown day” no matter what number we pass in. Add the _ catch-all-pattern back to weekday function.

If Expression vs Case Expression

Does this mean all if expressions can be replaced with case? Not necessarily. A case expression works by matching a pattern, whereas an if expression checks whether a condition is true or not. For example, the following code doesn’t really have a pattern.

escapeEarth velocity speed =
    if velocity > 11.186 then
        "Godspeed"
    else if speed == 7.67 then
        "Stay in orbit"
    else
        "Come back"

If we attempt to re-write it with a case expression, we will get an error. Add the following function definition right above main in Playground.elm.

escapeEarthWithCase velocity speed =
    case (velocity, speed) of
        (velocity > 11.186) ->
            "Godspeed"

        (speed == 7.67) ->
            "Stay in orbit"

        _ ->
            "Come back"


main
    ...

If you refresh the page at http://localhost:8000/elm-examples/Playground.elm, you should see the following error.

The reason why Elm is throwing an error is because there is no pattern to match here. All we have is a couple of disparate conditions. More importantly, the part before -> has to be a pattern. It can’t be any expression. Here we are trying to compare the given velocity and speed with some number using an expression.

However, if we are trying to figure out which orbit our spaceship can park on then we can use a case expression for that. Add the following function definition right above main in Playground.elm.

whereToPark speed =
    case speed of
        7.67 ->
            "Low Earth Orbit"

        3.8 ->
            "Medium Earth Orbit"

        3.07 ->
            "Geostationary Orbit"

        _ ->
            "Nowhere"


main =
    ...

Now let’s apply whereToPark function in main.

main =
    whereToPark 7.67
        |> Html.text

Remove the escapeEarthWithCase function definition from Playground.elm and refresh the page at http://localhost:8000/elm-examples/Playground.elm. You should see “Low Earth Orbit”.

To summarize, if we have disparate conditions to check then if expression is a good fit, but if we need to match an expression to a pattern, case expression is a better fit.

Back to top

New chapters are coming soon!

Sign up for the Elm Programming newsletter to get notified!

* indicates required
Close