2011-09-14 36 views
11

Tengo un pequeño problema en el patrón que coincide con un objeto en Scala cuando está parametrizado con un nombre de clase totalmente calificado. Esto se basa en Scala 2.9.0.1. ¿Alguien sabe qué pasa con este código?Scala: problema de coincidencia de patrón con nombres de clase totalmente calificados en la parametrización

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] => 

¿Por qué funciona la primera versión, pero esta última falla? El problema solo parece ocurrir cuando se usa un nombre de clase completamente calificado para la parametrización.

Respuesta

12

Desde el Scala Language Specification, Sección 8.1 Patrones, el identificador después de la: tiene que ser lo que se conoce como un patrón de tipo, definido en la Sección 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.

Por lo tanto, sintácticamente, no se puede usar una clase totalmente calificada como un patrón variable de tipo EN ESTA POSICIÓN. Sin embargo, puede utilizar un alias de tipo, por lo que:

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

devolverá 6 como se esperaba. El problema es que como señala Alan Burlison, la siguiente también devuelve 6:

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

porque el tipo se está borrando. Puede ver esto ejecutando el REPL o scalac con la opción -unchecked.

+0

Wow. Llegué a esto hoy y finalmente encontré esta pregunta. No tenía idea de que existiera un "patrón variable de tipo" en Scala. ¿Qué más me sigue ocultando en el SLS ...? –

+2

Algunos de los huevos de Pascua solo se activan el 1/4 y Pascua. –

+0

Comencé un hilo sobre esto en https://groups.google.com/d/msg/scala-language/2PNDjkI47Ao/MCQw7RzNUwcJ –

3

De hecho, su primer ejemplo tampoco funciona. Si ejecuta el REPL con -unchecked, verá el siguiente error:

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

lo que no puede hacer realmente lo que está tratando de hacer - en tiempo de ejecución que no hay diferencia entre una lista [Entero ] y una lista [AnythingElse], por lo que no puede coincidir con el patrón en él. Usted puede ser capaz de hacer esto con un manifiesto, ver http://ofps.oreilly.com/titles/9780596155957/ScalasTypeSystem.html#Manifests y http://www.scala-blogs.org/2008/10/manifests-reified-types.html

+0

No creo que el borrado del tipo fuera el objetivo de la pregunta. Qué tal esto: '" foo ".asInstanceOf [Any] match {'
'case x: Seq [Integer] =>'
'case y: Seq [java.lang.Integer] =>'
'}' – Jamil

+0

@Jamil, creo que 'Seq [java.lang.Integer]' es solo un error de sintaxis. Creo que el compilador está tratando 'java.lang.Integer' como un identificador y no pueden tener puntos en ellos. Puede demostrar esto rodeando 'java.lang.Integer' en comillas inversas - luego se compilará, pero igual recibirá la misma advertencia de borrado que con simple' Entero '. Estoy de acuerdo en que el error es engañoso, pero no es tan sorprendente teniendo en cuenta que en realidad no se puede hacer lo que @Frank está tratando de hacer de todos modos. –

+0

'java.lang.Integer' es un tipo, no una variable. Además Scala se une a la variable cuando usas el patrón Constructor, o tupla o secuencia, etc. Curiosamente, si uso el alias 'tipo myint = java.lang.Integer' Scala no se queja – Jamil

Cuestiones relacionadas