JIT: for Loops, Generators, and Guards

If you’re not familiar with Scala, you’ll need to know about for loops, generators, and guards before we work on the next aspect of the TDL app.


The first key is that every Scala for loop begins with a generator. A generator is a source of data, such as a list or stream. The simplest possible generators look like this:

for i <- 1 to 3 do println(i)    // 1st example

val xs = List(1, 2, 3)           // 2nd example
for x <- xs do println(x)

Those are for loops. They’re called loops — and not expressions — because they loop over those values for some side effect, which is printing in this case.

Conversely, for/yield combinations are called expressions because they yield a value, and you typically assign that value to a variable:

val xs = List(1, 2, 3)
val ys = for x <- xs yield x * 2

You often use a for/yield expression to write a function:

def double(xs: List[Int]): List[Int] =
    for x <- xs yield x * 2

When you’re new to this syntax, this style may be easier to read:

def double(xs: List[Int]): List[Int] =
        x <- xs
        x * 2

Multiple generators

for loops and expressions can have as many generators as you need for your algorithm:

val rez = 
        i <- 1 to 2
        j <- 3 to 4
        k <- 5 to 6
        i + j + k

// rez: Vector(9, 10, 10, 11, 10, 11, 11, 12)

As shown in the comment, the result of this for expression is a Vector that contains the list of integers shown. (Vector is a specific type of sequence (Seq) that is immutable, and generally has very good performance in many different situations.)


Guards are basically if conditions that you add to the first part of for loops and expressions, and they look like this:

val newValues =
        i <- 1 to 5
        j <- 6 to 10
        if i > 3
        if j < 7
        i + j

// newValues: Vector(10, 11)

As shown, you can add as many generators and guards as you need for your algorithm.

As I mention in my other books, the benefit of Scala’s for syntax is that it separates your generators and guards (in the first section) from your business logic (which comes in the second section, after the do and yield keywords).