代码之家  ›  专栏  ›  技术社区  ›  oxbow_lakes

理解和局部映射的scala

  •  2
  • oxbow_lakes  · 技术社区  · 15 年前

    scala语言规范部分 六点一九 说:

    A表示理解 for (p <- e) yield e0 转换为 e.map { case p => e0 }

    所以…

    scala> val l : List[Either[String, Int]] = List(Left("Bad"), Right(1))
    l: List[Either[String,Int]] = List(Left(Bad), Right(1))
    
    scala> for (Left(x) <- l) yield x
    res5: List[String] = List(Bad)
    

    到现在为止,一直都还不错:

    scala> l.map { case Left(x) => x }
    <console>:13: warning: match is not exhaustive!
    missing combination          Right
    
           l.map { case Left(x) => x }
                 ^
    scala.MatchError: Right(1)
        at $anonfun$1.apply(<console>:13)
        at ...
    

    为什么第二个版本不起作用?或者更确切地说, 为什么第一个版本有效?

    3 回复  |  直到 15 年前
        1
  •  4
  •   Moritz    15 年前

    如果你在你的 for -理解编译器将实际插入对 filter 用一个 instanceOf -应用前检查 map .

    编辑:

    同样在第6.19节中也提到:

    发电机P<-E,如果G被转换为单个发电机P<-E,则后面跟着一个保护装置,带滤波器((x1,…,xn)=>G),其中x1,…,xn是P的自由变量。

    发电机在前面定义为:

    生成器::=pattern1__<-_expr[guard]

    检查字节码时,您将看到 滤波器 在呼叫之前 地图 .

        2
  •  2
  •   Landei    15 年前

    作为Eastsun备注的补充:scala 2.8有一个方法collect,在您的示例中可以使用它:

    l.collect { case Left(x) => x }
    //--> List[String] = List(Bad)
    
        3
  •  1
  •   Dave Griffith    15 年前

    scala 2.7语言规范,第83页,底部第二段(此处没有2.8规范)。插入用于生成器模式匹配的过滤器是理解翻译过程的第一步。

    一个警告是,上次我检查时,这对类型化模式不起作用,这可能会令人惊讶。所以在你的例子中

    for(x:Left <- l) yield x  
    

    不起作用,引发类型错误

    推荐文章