For expression in Scala
Tags: scala, devjournal
Published: 2019-09-26 11:26:51

---
title: For expression in Scala
published: true
description: 
tags: scala, devjournal
series: Learning Scala
---

For expressions in Scala may look similar to for loops in Java or other imperative languages, but they work closer to list comprehensions in Haskell or Python. One of the main differences is that a for loop in Java usually has side effects, i.e., it mutates something outside the loop. A for expression in Scala returns a `Sequence` instead.

Let's try a simple problem to understand how for expressions are useful. Imagine that we want to find all the prime numbers between `1` and a given number `n`.

With imperative for loops we could do something like this:

```javascript
const primesTo = n => {
  const primes = []
  for (let i = 1; i <= n; i++) {
    if (isPrime(i)) primes.push(i)
  }
  return primes
}
```

We have an index that we increment until we reach the value `n`, and for each iteration we check if the number is prime and, in that case, we push it to an array. Observe that we are effectively mutating a value that's outside the scope of the for loop, the array `primes`.

In functional programming we could instead generate a sequence of numbers between `1` and `n` and then filter over the sequence to keep the numbers that are prime.

```scala
def primesTo (n: Int): Seq[Int] =
  (1 to n) filter isPrime
```

It is not relevant for this topic, but here's my naive implementation of `isPrime` in Scala.

```scala
def isPrime (n: Int): Boolean =
  (2 until n) forall (n % _ != 0)
```

The for expression in Scala takes one or more generators and, optionally, filters. A generator takes the form of `x <- <collection>` and a filter takes the form of `if <condition>`. So let's rewrite our `primesTo` function with a for expression.

```scala
def primesTo (n: Int): Seq[Int] =
  for (i <- (1 to n) if isPrime(i)) yield i
```

Not a big difference so far. One could even argue that it's longer than the previous example. However, for expressions can make the code more readable when we enter the realm of nested sequences.

Let's try with another problem. What if we want to find all combinations of three integers smaller than `n` that fulfill the [Pythagorean theorem](https://en.wikipedia.org/wiki/Pythagorean_theorem)?

With imperative for loops we could do something like this:

```javascript
const pythagorean = n => {
  const result = []
  for (let a = 1; a < n; a++) {
    for (let b = 1; b < a; b++) {
      for (let c = 1; c < b; c++) {
        if (a * a === b * b + c * c) {
          result.push([ a, b, c ])
        }
      }
    }
  }
  return result
}
```

And if we try to generate a sequence and filter over it in Scala we could do something similar to this:

```scala
def pythagorean (n: Int): Seq[(Int, Int, Int)] =
  (1 until n) flatMap (a =>
    (1 until a) flatMap (b =>
      (1 until b) map (c => (a, b, c))
    )
  ) filter (v => v._1 * v._1 == v._2 * v._2 + v._3 * v._3)
```

It's not entirely horrible, but at this point it's not really the most readable code ever.

In for expressions we can use multiple generators, so we don't need as many indentation levels as in the previous examples.

```scala
def pythagorean (n: Int): Seq[(Int, Int, Int)] =
  for {
    a <- (1 until n)
    b <- (1 until a)
    c <- (1 until b)
    if a * a == b * b + c * c
  } yield (a, b, c)
```

Notice that in this example we added the generators and filters between `{}` instead of `()`. The difference between these two is that with parenthesis we need to add a semicolon between different generators, while with curly brackets we can skip them, which is convenient when we are separating the generators with new lines.

In summary, for expressions provide a more readable syntax to work with nested sequences.