2011-12-12 29 views
6

我定義了一個自定義的提取以獲取列表的最後一個元素,如https://stackoverflow.com/a/6697749/1092910比賽順序爲:與提取

object :+ { 
    def unapply[A](l: List[A]): Option[(List[A], A)] = { 
    if (l.isEmpty) 
     None 
    else 
     Some(l.init, l.last) 
    } 
} 

現在這個匹配「好」:

List(1, 2, 3) match { 
    case init :+ last => "good" 
    case head :: tail => "bad" 
} 

但是,如果我添加另一個子句,它現在突然匹配「bad」:

List(1, 2, 3) match { 
    case List(7) => "never" 
    case init :+ last => "good" 
    case head :: tail => "bad" 
} 

此行爲的原因是什麼?

+0

它看起來像一個錯誤。我可以嘗試詢問郵件列表中的一個。 – huynhjl

+1

使用'scalac -print'進行編譯,似乎編譯器正在對模式進行一些優化,併合並了對「List(7)」和「head :: tail」的測試。它首先檢查它是否是Int列表,然後檢查第一個元素是否爲7,如果不是,則立即落入'head :: tail'並匹配'head :: tail'。這看起來像編譯器中的錯誤。 – markmarch

回答

6

它是#1697/2337和一打重複。

https://issues.scala-lang.org/browse/SI-1697

它看起來肯定地說,它不會被固定在直接的方式,而是通過刪除模式匹配的virtpatmat實施。嘗試使用-Yvirtpatmat進行最近的編譯並編譯,你會得到正確的答案。