- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
A Tour of Scala: Sequence Comprehensions
Created by admin on 2008-07-05.
Updated: 2010-08-09, 14:06
Scala offers a lightweight notation for expressing sequence comprehensions. Comprehensions have the formfor
(enums) yield
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
(from, from + 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 filter
, map
, 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 + ")") }