Skip to content

Commit 3b06488

Browse files
committed
zh-cn for Scala Tour:for-comprehensions.md
1 parent f34e341 commit 3b06488

File tree

1 file changed

+53
-1
lines changed

1 file changed

+53
-1
lines changed

_zh-cn/tour/for-comprehensions.md

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
layout: tour
3-
title: For Comprehensions
3+
title: For 循环推导
44

55
discourse: false
66

@@ -13,3 +13,55 @@ language: zh-cn
1313
next-page: generic-classes
1414
previous-page: extractor-objects
1515
---
16+
17+
Scala 提供一个轻量级的标记方式用来表达 *序列推导*. 推导使用以下形式 `for (enumerators) yield e`, 此处 `enumerators` 指一组以分号分隔的迭代器. 一个 *enumerator* 要么是一个产生新变量的构造器, 要门是一个过滤器. 推导在循环的每一次迭代中都会计算 `e` 值, 并保存在集合中, 循环结束后返回该集合.
18+
19+
看下例:
20+
21+
```tut
22+
case class User(name: String, age: Int)
23+
24+
val userBase = List(User("Travis", 28),
25+
User("Kelly", 33),
26+
User("Jennifer", 44),
27+
User("Dennis", 23))
28+
29+
val twentySomethings = for (user <- userBase if (user.age >=20 && user.age < 30))
30+
yield user.name // i.e. add this to a list
31+
32+
twentySomethings.foreach(name => println(name)) // prints Travis Dennis
33+
```
34+
这里 `for` 循环后面使用的 `yield` 语句实际上会创建一个 `List`. 因为当我们说 `yield user.name` 的时候, 它实际上是一个 `List[String]`. `user <- userBase` 是循环迭代器, `if (user.age >=20 && user.age < 30)` 是循环守卫用来过滤掉那些年龄不是20多岁的人.
35+
36+
下面这个例子复杂一些, 使用了两个迭代器. 它计算了 `0``n-1` 的所有两两求和为 `v` 的数字的组合:
37+
38+
```tut
39+
def foo(n: Int, v: Int) =
40+
for (i <- 0 until n;
41+
j <- i until n if i + j == v)
42+
yield (i, j)
43+
44+
foo(10, 10) foreach {
45+
case (i, j) =>
46+
println(s"($i, $j) ") // prints (1, 9) (2, 8) (3, 7) (4, 6) (5, 5)
47+
}
48+
49+
```
50+
这里 `n == 10``v == 10`. 在第一次迭代时, `i == 0` 并且 `j == 0` 所以 `i + j != v` 因此没有返回值被生成. 在 `i` 的值递增到 `1` 之前, `j` 的值又递增了 9 次. 如果没有 `if` 守护语句, 上面的例子只会打印出如下的结果:
51+
```
52+
53+
(0, 0) (0, 1) (0, 2) (0, 3) (0, 4) (0, 5) (0, 6) (0, 7) (0, 8) (0, 9) (1, 1) ...
54+
```
55+
56+
注意推导并不局限于使用列表. 任何数据类型只要支持 `withFilter`, `map`, 和 `flatMap` 操作 (不同数据类型可能支持不同的操作) 都可以用来做序列推导.
57+
58+
你可以在使用推导时省略 `yield` 语句. 此时推导会返回 `Unit`. 当你想要执行一些副作用的时候这很有用. 下面的例子输出和上面相同的结果, 但是没有使用 `yield`:
59+
60+
```tut
61+
def foo(n: Int, v: Int) =
62+
for (i <- 0 until n;
63+
j <- i until n if i + j == v)
64+
println(s"($i, $j)")
65+
66+
foo(10, 10)
67+
```

0 commit comments

Comments
 (0)