for表达式
-
for
表达式一般是for ( seq ) yield expr
,seq
是一个序列,包含有生成器、定义和过滤器,它们用分号隔开。for { p <- persons // a generator n = p.name // a definition if (n startsWith "To") // a filter } yield n
pat <- expr
,expr
通常返回一个列表。如果匹配成功,模式中的变量就会成功绑定,如果匹配不成功,当前元素仅仅就是被丢掉了,并不会有MatchError
抛出。
定义的格式如下:pat = expr
过滤器的格式:if expr
,过滤器会将迭代中所有让expr
为false
的元素丢弃。for
中可以含有多个生成器,如果一个for
表达式中有多个生成器,则出现在后面的生成器是嵌套在前面的生成器中,后面的生成器出现的更频繁。
for
表示法本质上跟数据库查询语言的通用操作是等效的。
用for推导式进行翻译
- 每个
for
表达式都可以使用map,flatMap
和withFilter
来表示。for (x <- expr_1) yield expr_2 expr_1.map(x => expr_2) for (x <- expr_1 if expr_2) yield expr_3 expr_1 withFilter (x => expr2) map (x => expr3) for (x <- expr_1; y <- expr_2) yield expr_3 expr_1.flatMap(x => (y.map(y => expr3))
for
语句中,yield
的表达式expr_3
是用于最后一个生成器的map
函数。剩下的生成器都是flatMap
。for (x <- expr_1; y = expr_2; seq) yield expr_3 for ((x, y) <- for (x <- expr_1) yield (x, expr_2); seq) yield expr_3
for
中的定义y = expr_2
会在每一次迭代x
的时候进行计算,如果是和x
无关的变量,计算时很耗费,最好把和x
无关的操作放在for
表达式的外面。如果是没有yield
表达式,会直接翻译成foreach
。for (x <- expr_1) body expr_1 foreach (x => body)
map,faltMap
和withFilter
的应用都可以使用for
表达式进行表达。 - 由于for表达式的翻译仅仅依赖
map、faltMap、withFilter
和foreach
,则定义了这些方法的结构也可以生成各种各样的for
表达式。 - 如果
withFilter
每次都产出一个序列的话,对于序列很大的情况下消耗时间很大,一般的做法返回一个"记住"元素需要被过滤的包装对象,然后再继续处理。