我看了《Programming in Scala》一书,仍然对 Scala yield 关键字的理解不甚清楚。起初我觉得 Scala yield 的与 Ruby 的 yield 是同样,Ruby 中 yield 是被传入代码块的占位符。Scala 中的 yield 关键字好像老是在 for 循环中用的. 下面一些例子能够帮助你更好的理解 yield 关键字。下面是摘自 《Programming in Scala》关于 yield 的解释:数组
For each iteration of your for loop, yield generates a value which will be remembered. It's like the for loop has a buffer you can't see, and for each iteration of your for loop, another item is added to that buffer. When your for loop finishes running, it will return this collection of all the yielded values. The type of the collection that is returned is the same type that you were iterating over, so a Map yields a Map, a List yields a List, and so on.oop
Also, note that the initial collection is not changed; the for/yield construct creates a new collection according to the algorithm you specify.测试
上面那段话的意义就是,for 循环中的 yield 会把当前的元素记下来,保存在集合中,循环结束后将返回该集合。Scala 中 for 循环是有返回值的。若是被循环的是 Map,返回的就是 Map,被循环的是 List,返回的就是 List,以此类推。this
基于上面的信息,来看几个例子:spa
scala>
for
(i <-
1
to
5
)
yield
i
res
10
:
scala.collection.immutable.IndexedSeq[Int]
=
Vector(
1
,
2
,
3
,
4
,
5
)
前面的例子都不算什么,还只是个开始. 接下来, 对咱们初始集合的每一个元素作一次翻倍:scala
scala>
for
(i <-
1
to
5
)
yield
i *
2
res
11
:
scala.collection.immutable.IndexedSeq[Int]
=
Vector(
2
,
4
,
6
,
8
,
10
)
这里是 for/yield 循环的求模操做:code
scala>
for
(i <-
1
to
5
)
yield
i
%
2
res
12
:
scala.collection.immutable.IndexedSeq[Int]
=
Vector(
1
,
0
,
1
,
0
,
1
)
Scala 数组上的 for 循环 yield 的例子orm
以前提到过 for 循环 yield 会构造并返回与给定集合相同类型的集合. 为此, 咱们来看看如下用 Scala 数组上的例子. 注意把 yield(咱们能够把 yield 用做一个动词) 出来的集合类型与前面的几个例子对比:ci
scala>
val
a
=
Array(
1
,
2
,
3
,
4
,
5
)
a
:
Array[Int]
=
Array(
1
,
2
,
3
,
4
,
5
)
scala>
for
(e <- a)
yield
e
res
5
:
Array[Int]
=
Array(
1
,
2
,
3
,
4
,
5
)
scala>
for
(e <- a)
yield
e *
2
res
6
:
Array[Int]
=
Array(
2
,
4
,
6
,
8
,
10
)
scala>
for
(e <- a)
yield
e
%
2
res
7
:
Array[Int]
=
Array(
1
,
0
,
1
,
0
,
1
)
正如你所见, 例子中被 yield 的是 Array[Int], 而更早的例子中返回的类型是 IndexedSeq[Int].rem
for 循环, yield, 和守卫( guards) (for loop 'if' conditions)
假如你熟悉了 Scala 复杂的语法, 你就会知道能够在 for 循环结构中加上 'if' 表达式. 它们做为测试用,一般被认为是一个守卫,你能够把它们与 yield 语法联合起来用。参见::
scala>
val
a
=
Array(
1
,
2
,
3
,
4
,
5
)
a
:
Array[Int]
=
Array(
1
,
2
,
3
,
4
,
5
)
scala>
for
(e <- a
if
e >
2
)
yield
e
res
1
:
Array[Int]
=
Array(
3
,
4
,
5
)
如上, 加上了 "if e > 2" 做为守卫条件用以限制获得了只包含了三个元素的数组.
Scala for 循环和 yield 的例子 - 总结
若是你熟悉 Scala 的 loop 结构, 就会知道在 for 后的圆括号中还能够许更多的事情. 你能够加入 "if" 表达式,或别的语句, 好比下面的例子,能够组合多个 if 语句:
def
scalaFiles
=
for
{
file <- filesHere
if
file.isFile
if
file.getName.endsWith(
".scala"
)
}
yield
file
yield 关键字的简短总结:
针对每一次 for 循环的迭代, yield 会产生一个值,被循环记录下来 (内部实现上,像是一个缓冲区).
当循环结束后, 会返回全部 yield 的值组成的集合.
返回集合的类型与被遍历的集合类型是一致的.
但愿上面的例子结诸位有所帮助.