Learn Scala 3 Fast: Constructs: for Loops

Now that we’ve seen the List class we can begin looking at for loops, which let us iterate over elements in a sequence. For example, given this list:

val ints = List(1, 2, 3)

This REPL example shows how to iterate over every element in the list to print them with the println function:

scala> for i <- ints do println(i)
1
2
3

You can infer from that example that the general syntax of a for loop is:

for element <- listOfElements do somethingToDoWith(element)

When the “something to do” part of your code requires multiple lines, use this syntax:

for
    i <- ints
do
    // this doesn’t really require multiple lines,
    // but imagine that it does
    val j = i * 10
    println(j)

Here’s another example that shows another way the for/do loop can be formatted:

val names = List("adam", "alex", "bob")

// again imagine that this requires multiple lines:
for name <- names do
    val capName = name.capitalize
    println(capName)

Either of these indentation styles will work, and that example results in this output:

Adam
Alex
Bob

I keep noting that you should imagine that this code requires multiple lines, and that’s because it really doesn’t; it can all be on one line, like this:

for name <- names do println(name.capitalize)

Personally, I often find myself writing multiple lines of code, and then realizing, “Wait, I can condense this, and this, and then that,” and I end up with just one or two lines of code. Having concise — but still readable! — code often happens in Scala.

Remembering EOP

Earlier I mentioned EOP — Expression-Oriented Programming. Remember that in EOP we program using expressions and not statements.

However, for loops are a construct that don’t really return anything. Because of this they are effectively statements, and are only used for their side effects. This is something I never thought about in Java and other OOP languages, but once you’re exposed to EOP, you realize that something now feels different about for loops. It starts to occur to you, “Hmm, I see now that this is a statement, not an expression.” It’s not that statements are necessarily bad — you certainly need to be able to print — but they begin to stand out to you.

Two notes

As a first note, I mentioned earlier that technically the for loop shown does have a return type. That type is named Unit, and it’s like void or Void in some other languages. This just means that the return type is empty and essentially useless. This leads to another important point: every programming statement will have a Unit return type, because statements are always used for their side effects, and have no useful return type.

The println function is a great example of this. We know that it’s only used for its side effect of printing to STDOUT, and this is its actual type signature:

def println(x: Any): Unit = ???

Even though I haven’t discussed functions yet, if you’ve worked with other programming languages you can probably tell that this is a function that takes a parameter named x whose type is Any, and it returns the Unit data type. So again, when you see that some block of code returns Unit, your first thought should be, “There’s a side effect here.”

The second note is to remember that wherever I demonstrate the List class, you can generally also use the Vector class, because both are immutable.

Exercises

The exercises for this lesson are available here.