2011-12-12 3 views
6

ho definito un estrattore personalizzato per ottenere l'ultimo elemento della lista, come in https://stackoverflow.com/a/6697749/1092910:fine partita con un estrattore

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

Ora, questo corrisponde a "buono":

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

Ma se io aggiungere un'altra clausola, che corrisponda a un tratto "cattivo" ora:

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

Qual è il motivo di questo comportamento?

+0

Sembra un bug. Posso provare a chiedere su una delle mailing list. – huynhjl

+1

Compilare con 'scalac -print', sembra che il compilatore stia facendo un'ottimizzazione con i pattern e ha unito il test per' List (7) 'e' head :: tail'. prima controlla se è una lista di Int, quindi controlla se il primo elemento è 7, se non lo è, cade immediatamente a 'head :: tail' e corrisponde a' head :: tail'. Questo sembra un bug nel compilatore. – markmarch

risposta

6

È # 1697/2337 e una dozzina di duplicati.

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

Sembra sicuro di dire che non verrà risolto in maniera diretta, ma eliminando il matcher modello per l'attuazione virtpatmat. Prova una build recente e compila con -Yvirtpatmat, otterrai la risposta giusta.