Learn Scala 3 Fast: Constructs: Adding 'if' Clauses to 'for' Expressions

You can add if statements to for expressions, but in Scala they’re a little different, in what I think is a really smart approach. For example, given this list:

val fruits = List("apple", "banana", "cherry", "date")

In Scala, you could write an old-school for loop like this:

// don’t do this, there’s a better way
for
    f <- fruits
do
    if f.length > 5 then println(f)

That code prints this output, as desired:

banana
cherry

However, in Scala the correct approach is to add the if clause to the first part of the for expression, like this:

for
    f <- fruits
    if f.length > 5
do
    println(f)

As it turns out, this is a much better approach, because it separates our code into two distinct sections:

for
    f <- fruits        // generator
    if f.length > 5    // guard
do
    println(f)         // business logic

As shown, if expressions inside the generator area are called guards (which you can also think of as filters). A great thing about this approach is that you can put all of your generators and guards after the for keyword, and your business logic after the do (or yield in for expressions). It turns out that this “separation of concerns” makes our code much easier to read.

TIP: If you’re familiar with SQL, this is a bit like a SQL UPDATE statement, which has distinct UPDATE, SET, and WHERE clauses.

Here’s a similar example that uses a for expression instead of a for loop:

val capFruits =
    for
        f <- fruits
        // add as many guards as you need
        if f.length > 5
        if f.length < 10
        if f.startsWith("c")
    yield
        // add as much business logic as
        // you need here
        f.capitalize

As shown, you can add as many guards as you need, and as much business logic as you need for the current problem — and having them in separate code blocks makes your code easier to read.

If you run that code in the Scala REPL you’ll see that capFruits has this data type and content:

capFruits: List[String] = List(Cherry)

As a summary, you’ve now seen both generators and guards in both for loops and for expressions.

Exercises

The exercises for this lesson are available here.