You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Scala offers a lightweight notation for expressing *sequence comprehensions*. Comprehensions have the form `for (enumerators) yield e`, where `enumerators` 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 and returns a sequence of these values.
15
15
16
-
Here is an example:
17
-
16
+
Here's an example:
17
+
18
18
```tut
19
-
object ComprehensionTest1 extends App {
20
-
def even(from: Int, to: Int): List[Int] =
21
-
for (i <- List.range(from, to) if i % 2 == 0) yield i
22
-
Console.println(even(0, 20))
23
-
}
24
-
```
25
-
26
-
The for-expression in function 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.
19
+
case class User(val name: String, val age: Int)
27
20
28
-
The program yields the following output:
21
+
val userBase = List(new User("Travis", 28),
22
+
new User("Kelly", 33),
23
+
new User("Jennifer", 44),
24
+
new User("Dennis", 23))
29
25
26
+
val twentySomethings = for (user <- userBase if (user.age >=20 && user.age < 30))
27
+
yield user.name // i.e. add this to a list
28
+
29
+
twentySomethings.foreach(name => println(name)) // prints Travis Dennis
30
30
```
31
-
List(0, 2, 4, 6, 8, 10, 12, 14, 16, 18)
32
-
```
31
+
The `for` loop used with a `yield` statement actually creates a `List`. Because we said `yield user.name`, it's a `List[String]`. `user <- userBase` is our iterator and `if (user.age >=20 && user.age < 30)` is a guard that filters out users who are in their 20s.
32
+
33
+
Here is a more complicated example using two generators. It computes all pairs of numbers between `0` and `n-1` whose sum is equal to a given value `v`:
33
34
34
-
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`:
This example shows that comprehensions are not restricted to lists. The previous program uses iterators instead. Every datatype that supports the operations `withFilter`, `map`, and `flatMap` (with the proper types) can be used in sequence comprehensions.
50
-
51
-
Here's the output of the program:
52
45
53
46
```
54
-
(13, 19)
55
-
(14, 18)
56
-
(15, 17)
57
-
(16, 16)
47
+
Here `n == 10` and `v == 10`. On the first iteration, `i == 0` and `j == 0` so `i + j != v` and therefore nothing is yielded. `j` gets incremented 9 more times before `i` gets incremented to `1`. Without the `if` guard, this would simply print the following:
58
48
```
59
49
60
-
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.
61
-
Here's a program which is equivalent to the previous one but uses the special for comprehension returning `Unit`:
0 commit comments