2017-04-23 60 views
6

根据Scala语言规范的第6.19 for循环:斯卡拉推导/循环和类型化的模式

for (e <-p) e' 

被翻译成:

p <- e.withFilter{case p => true; case _ => false}.foreach{case p => e′} 

那么,为什么这个小程序:

object ForAndPatterns extends App { 
    class A() 
    class B() extends A 

    val list: List[A] = List(new A(), new B(), new B()) 

    for {b: B <- list} 
    println(b) 
} 

给出此编译错误:

Error:(7, 13) type mismatch; 
found : proves.ForAndPatterns.B => Unit 
required: proves.ForAndPatterns.A => ? 
    for {b: B <- list} 

当此表达式:

list.withFilter{case a: B => true; case _ => false}.foreach{case b => println(b)} 

没有给出错误。

+0

http://www.scala-lang.org/files/archive/spec/2.12/08-pattern-matching.html#irrefutable-patterns – pedrofurla

+0

'转换方案如下。在第一步中,每个生成器p < - e,其中p不是e的类型无可辩驳的被替换为'。这是一个无可辩驳的模式。 – pedrofurla

+1

@pedrofurla不,对于'A'类型,'b:B'不是无可辩驳的。 –

回答

10

你从规范中得到的翻译实际上是

list.withFilter{case b: B => true; case _ => false}.foreach{case b: B => println(b)} 

,但它仍然编译和作品。这似乎是Scala是失去了case并翻译成

list.withFilter{case b: B => true; case _ => false}.foreach{b: B => println(b)} 

这将给予同样的错误。

这原来是一个已知和旧的bug:https://github.com/scala/bug/issues/900

解决方法提供了:

object Typed { def unapply[A](a: A) = Some(a) } 

for { Typed(b: B) <- list } println(b)