From bac6beb18be16a86ae84eeb25708a0f1eb48da14 Mon Sep 17 00:00:00 2001 From: Travis Lee Date: Thu, 30 Mar 2017 19:47:53 +0200 Subject: [PATCH 1/2] Rewrote sequence comprehensions section of tour --- .../2017-02-13-sequence-comprehensions.md | 67 +++++++------------ 1 file changed, 24 insertions(+), 43 deletions(-) diff --git a/tutorials/tour/_posts/2017-02-13-sequence-comprehensions.md b/tutorials/tour/_posts/2017-02-13-sequence-comprehensions.md index 5fa828e337..7b73e9e7ca 100644 --- a/tutorials/tour/_posts/2017-02-13-sequence-comprehensions.md +++ b/tutorials/tour/_posts/2017-02-13-sequence-comprehensions.md @@ -13,58 +13,39 @@ previous-page: extractor-objects 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. -Here is an example: - +Here's an example: + ```tut -object ComprehensionTest1 extends App { - 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 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. +case class User(val name: String, val age: Int) -The program yields the following output: +val userBase = List(new User("Travis", 28), + new User("Kelly", 33), + new User("Jennifer", 44), + new User("Dennis", 23)) +val twentySomethings = for (user <- userBase if (user.age >=20 && user.age < 30)) + yield user.name // i.e. add this to a list + +twentySomethings.foreach(name => println(name)) // prints Travis Dennis ``` -List(0, 2, 4, 6, 8, 10, 12, 14, 16, 18) -``` +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. + +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`: -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`: - ```tut -object ComprehensionTest2 extends App { - def foo(n: Int, v: Int) = - for (i <- 0 until n; - j <- i until n if i + j == v) yield - (i, j); - foo(20, 32) foreach { - case (i, j) => - println(s"($i, $j)") - } +def foo(n: Int, v: Int) = + for (i <- 0 until n; + j <- i until n if i + j == v) + yield (i, j) + +foo(10, 10) foreach { + case (i, j) => + print(s"($i, $j) ") // prints (1, 9) (2, 8) (3, 7) (4, 6) (5, 5) } -``` - -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. - -Here's the output of the program: ``` -(13, 19) -(14, 18) -(15, 17) -(16, 16) +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: ``` -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 returning `Unit`: - +(0, 0) (0, 1) (0, 2) (0, 3) (0, 4) (0, 5) (0, 6) (0, 7) (0, 8) (0, 9) (1, 1) ... ``` -object ComprehensionTest3 extends App { - for (i <- Iterator.range(0, 20); - j <- Iterator.range(i, 20) if i + j == 32) - println(s"($i, $j)") -} -``` - From 2c6f8fa401729bd9cac705a9b3b363b43137e1a0 Mon Sep 17 00:00:00 2001 From: Travis Lee Date: Fri, 26 May 2017 18:02:41 +0200 Subject: [PATCH 2/2] Ichoran's suggestions --- ...nce-comprehensions.md => 2017-02-13-for-comprehensions.md} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename tutorials/tour/_posts/{2017-02-13-sequence-comprehensions.md => 2017-02-13-for-comprehensions.md} (97%) diff --git a/tutorials/tour/_posts/2017-02-13-sequence-comprehensions.md b/tutorials/tour/_posts/2017-02-13-for-comprehensions.md similarity index 97% rename from tutorials/tour/_posts/2017-02-13-sequence-comprehensions.md rename to tutorials/tour/_posts/2017-02-13-for-comprehensions.md index 7b73e9e7ca..cf9f4cf166 100644 --- a/tutorials/tour/_posts/2017-02-13-sequence-comprehensions.md +++ b/tutorials/tour/_posts/2017-02-13-for-comprehensions.md @@ -1,6 +1,6 @@ --- layout: tutorial -title: Sequence Comprehensions +title: For Comprehensions disqus: true @@ -36,7 +36,7 @@ Here is a more complicated example using two generators. It computes all pairs o def foo(n: Int, v: Int) = for (i <- 0 until n; j <- i until n if i + j == v) - yield (i, j) + yield (i, j) foo(10, 10) foreach { case (i, j) =>