Chapter 23《For Expressions Revisited》

for表达式

  • for表达式一般是for ( seq ) yield exprseq是一个序列,包含有生成器、定义和过滤器,它们用分号隔开。
    for {
    p <- persons  // a generator
    n = p.name    // a definition
    if (n startsWith "To")  // a filter
    } yield n
    
    生成器的格式如下,pat <- exprexpr通常返回一个列表。如果匹配成功,模式中的变量就会成功绑定,如果匹配不成功,当前元素仅仅就是被丢掉了,并不会有MatchError抛出。
    定义的格式如下:pat = expr
    过滤器的格式:if expr,过滤器会将迭代中所有让exprfalse的元素丢弃。for中可以含有多个生成器,如果一个for表达式中有多个生成器,则出现在后面的生成器是嵌套在前面的生成器中,后面的生成器出现的更频繁。
    for表示法本质上跟数据库查询语言的通用操作是等效的。

用for推导式进行翻译

  • 每个for表达式都可以使用map,flatMapwithFilter来表示。
    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,faltMapwithFilter的应用都可以使用for表达式进行表达。
  • 由于for表达式的翻译仅仅依赖map、faltMap、withFilterforeach,则定义了这些方法的结构也可以生成各种各样的for表达式。
  • 如果withFilter每次都产出一个序列的话,对于序列很大的情况下消耗时间很大,一般的做法返回一个"记住"元素需要被过滤的包装对象,然后再继续处理。

你可能感兴趣的:(Chapter 23《For Expressions Revisited》)