2011-09-14 8 views
11

Ho un piccolo problema nel modello che corrisponde ad un oggetto in Scala quando è parametrizzato con un nome di classe completo. Questo è basato su Scala 2.9.0.1. Qualcuno sa cosa c'è di sbagliato con questo codice?Scala: problema di corrispondenza del modello con nomi di classi completamente qualificati nella parametrizzazione

scala> "foo" match { 
| case y : Seq[Integer] => 
| case y : Seq[java.lang.Integer] => 
<console>:3: error: ']' expected but '.' found. 
    case y : Seq[java.lang.Integer] => 

Perché la prima versione funziona, ma il secondo non funziona? Il problema sembra verificarsi solo quando per la parametrizzazione viene utilizzato un nome classe completo.

risposta

12

Dal Scala Language Specification, sezione 8.1 Patterns, l'identificativo dopo il: deve essere quello che viene definito come un tipo di modello, definito nella sezione 8.2:

Type patterns consist of types, type variables, and wildcards. A type pattern T is of one of the following forms:

...

A parameterized type pattern T [a(1), . . . , a(n)], where the a(i) are type variable patterns or wildcards _. This type pattern matches all values which match T for some arbitrary instantiation of the type variables and wildcards. The bounds or alias type of these type variable are determined as described in (§8.3).

...

A type variable pattern is a simple identifier which starts with a lower case letter. However, the predefined primitive type aliases unit, boolean, byte, short, char, int, long, float, and double are not classified as type variable patterns.

Quindi, sintatticamente, non è possibile utilizzare una classe pienamente qualificata come tipo di modello variabile IN QUESTA POSIZIONE. Tuttavia, è possibile utilizzare un alias di tipo:

type JavaInt = java.lang.Integer 
List(new java.lang.Integer(5)) match { 
    case y: Seq[JavaInt] => 6 
    case _ => 7 
} 

restituirà 6 come previsto. Il problema è che, come sottolinea Alan Burlison, quanto segue restituisce anche 6:

List("foobar") match { 
    case y: Seq[JavaInt] => 6 
    case _ => 7 
} 

perché il tipo è stato cancellato. Puoi vederlo eseguendo il REPL, o scalac con l'opzione -unchecked.

+0

Wow. L'ho colpito oggi e alla fine ho trovato questa domanda. Non avevo idea che esistesse un tipo di "modello variabile" persino in Scala. Cos'altro mi sta ancora nascondendo in SLS ...? –

+2

Alcune delle uova di Pasqua si attivano solo su 1/4 e Pasqua. –

+0

Ho iniziato una discussione su questo https://groups.google.com/d/msg/scala-language/2PNDjkI47Ao/MCQw7RzNUwcJ –

3

In effetti il ​​tuo primo esempio non funziona neanche. Se si esegue il REPL con -unchecked, si vedrà il seguente errore:

warning: non variable type-argument Integer in type pattern Seq[Integer] is unchecked since it is eliminated by erasure

così non si può davvero fare ciò che si sta cercando di fare - a run-time non c'è alcuna differenza tra un elenco [Integer ] e una lista [AnythingElse], quindi non è possibile associarvi a modelli. Potreste essere in grado di fare questo con un manifesto, vedi http://ofps.oreilly.com/titles/9780596155957/ScalasTypeSystem.html#Manifests e http://www.scala-blogs.org/2008/10/manifests-reified-types.html

+0

Non penso che il tipo di cancellazione sia stato il punto della domanda. Che ne dici di questo: '" foo ".asInstanceOf [Any] match {'
'case x: Seq [Intero] =>'
'caso y: Seq [java.lang.Integer] =>'
'}' – Jamil

+0

@ Jamil, credo che 'Seq [java.lang.Integer]' sia solo un errore di sintassi. Credo che il compilatore tratti 'java.lang.Integer' come un identificatore e non possano avere dei punti al loro interno. Puoi dimostrarlo circondando 'java.lang.Integer' in backquotes - verrà poi compilato ma riceverai comunque lo stesso avviso di cancellazione che fai con plain' Integer'. Sono d'accordo che l'errore è fuorviante, ma non è poi così sorprendente considerando che non puoi davvero fare quello che @Frank sta cercando di fare comunque. –

+0

'java.lang.Integer' è un tipo non una variabile. Inoltre Scala si lega alla variabile quando si utilizza il pattern Constructor, o tupla o sequenza ecc. Stranamente, se uso l'alias 'type myint = java.lang.Integer 'Scala non si lamenta – Jamil

Problemi correlati