Skip to content

Commit bac6beb

Browse files
committed
Rewrote sequence comprehensions section of tour
1 parent a049f92 commit bac6beb

File tree

1 file changed

+24
-43
lines changed

1 file changed

+24
-43
lines changed

tutorials/tour/_posts/2017-02-13-sequence-comprehensions.md

Lines changed: 24 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -13,58 +13,39 @@ previous-page: extractor-objects
1313

1414
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.
1515

16-
Here is an example:
17-
16+
Here's an example:
17+
1818
```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)
2720
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))
2925
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
3030
```
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`:
3334

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`:
35-
3635
```tut
37-
object ComprehensionTest2 extends App {
38-
def foo(n: Int, v: Int) =
39-
for (i <- 0 until n;
40-
j <- i until n if i + j == v) yield
41-
(i, j);
42-
foo(20, 32) foreach {
43-
case (i, j) =>
44-
println(s"($i, $j)")
45-
}
36+
def foo(n: Int, v: Int) =
37+
for (i <- 0 until n;
38+
j <- i until n if i + j == v)
39+
yield (i, j)
40+
41+
foo(10, 10) foreach {
42+
case (i, j) =>
43+
print(s"($i, $j) ") // prints (1, 9) (2, 8) (3, 7) (4, 6) (5, 5)
4644
}
47-
```
48-
49-
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:
5245
5346
```
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:
5848
```
5949
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`:
62-
50+
(0, 0) (0, 1) (0, 2) (0, 3) (0, 4) (0, 5) (0, 6) (0, 7) (0, 8) (0, 9) (1, 1) ...
6351
```
64-
object ComprehensionTest3 extends App {
65-
for (i <- Iterator.range(0, 20);
66-
j <- Iterator.range(i, 20) if i + j == 32)
67-
println(s"($i, $j)")
68-
}
69-
```
70-

0 commit comments

Comments
 (0)