This page is no longer maintained — Please continue to the home page at www.scala-lang.org

A Tour of Scala: Sequence Comprehensions

Scala offers a lightweight notation for expressing sequence comprehensions. Comprehensions have the formfor (enumsyield e, where enums refers to a semicolon-separated list of enumerators. An enumerator is either a generator which introduces new variables, or it is a filter. A comprehension evaluates the body e for each binding generated by the enumerators enum and returns a sequence of these values.

Here is an example:

 

object ComprehensionTest1 extends Application {
  def even(from: Int, to: Int): List[Int] =
    for (i <- List.range(from, to) if i % 2 == 0) yield i
  Console.println(even(0, 20))
}

 

The for-expression in function even introduces a new variable i of type Int which is subsequently bound to all values of the list List(fromfrom + 1, ..., to - 1). The guard if i % 2 == 0 filters out all odd numbers so that the body (which only consists of the expression i) is only evaluated for even numbers. Consequently, the whole for-expression returns a list of even numbers.

The program yields the following output:

List(0, 2, 4, 6, 8, 10, 12, 14, 16, 18)

Here is a more complicated example which computes all pairs of numbers between 0 and n-1 whose sum is equal to a given value v:

 

object ComprehensionTest2 extends Application {
  def foo(n: Int, v: Int) =
    for (i <- 0 until n;
         j <- i + 1 until n if i + j == v) yield
      Pair(i, j);
  foo(20, 32) foreach {
    case (i, j) =>
      println("(" + i + ", " + j + ")")
  }
}

 

This example shows that comprehensions are not restricted to lists. The previous program uses iterators instead. Every datatype that supports the operations filtermap, and flatMap (with the proper types) can be used in sequence comprehensions.

Here's the output of the program:

(13, 19)
(14, 18)
(15, 17)

There is also a special form of sequence comprehension which returns Unit. Here the bindings that are created from the list of generators and filters are used to perform side-effects. The programmer has to omit the keyword yield to make use of such a sequence comprehension.

Here's a program which is equivalent to the previous one but uses the special for comprehension returningUnit:

 

object ComprehensionTest3 extends Application {
  for (i <- Iterator.range(0, 20);
       j <- Iterator.range(i + 1, 20) if i + j == 32)
    println("(" + i + ", " + j + ")")
}

 

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland