2012-09-09 19 views
5

¿Podría alguien explicar por qué se compila el siguiente código?Coincidencia del modelo de Scala e inferencia de tipo

Option("foo") match { 
    case x: List[String] => println("A") 
    case _ => println("B") 
} 

Esto me da una advertencia (esperada) sobre el borrado de tipo, pero aún compila. Esperé que esto arrojara un error de tipo, como ocurre si coincidiera en "foo" en lugar de Option("foo").

Gracias!

+1

Parece un error. Yo lo reportaría. – sschaef

Respuesta

2

Supongo que el compilador trata Option y List como Product, por lo que se compila. Como dices, se espera la advertencia sobre el borrado de tipos. Aquí hay un ejemplo que utiliza otro producto:

scala> Option("foo") match { 
| case x: Tuple2[String,String] => println("TUPLE") 
| case x: List[String] => println("LIST") 
| case _ => println("OTHER") 
| } 
<console>:9: warning: non variable type-argument String in type pattern (String, String)  is unchecked since it is eliminated by erasure 
      case x: Tuple2[String,String] => println("TUPLE") 
       ^
<console>:10: warning: non variable type-argument String in type pattern List[String] is unchecked since it is eliminated by erasure 
      case x: List[String] => println("LIST") 
       ^

ACTUALIZACIÓN w/clases de casos r/t (debido al comentario más abajo):

scala> case class Foo(bar: Int) 
defined class Foo 

scala> val y: Product = Foo(123) 
y: Product = Foo(123) 
+0

Parece que no tiene nada que ver con 'Producto'. Reemplacé 'Option (" foo ")' con mi propia clase de caso tomando un solo parámetro y no hay ningún error. – ghik

+2

Errr, las clases de casos extienden automáticamente el Producto. Ver la edición de respuesta. – timothy

+1

Bueno, está bien, pero en realidad no tiene que ser una clase de caso. La clase usual no final tampoco causa error. – ghik

0

me di cuenta que se muestra un error cuando la clase del el valor que coincide se declara como final (y sabemos que String es final). Todavía no sé por qué no hay ningún error sin eso.

4

El código está comentado, así que vamos a tomar un momento para saborear que:

/** If we can absolutely rule out a match we can fail early. 
    * This is the case if the scrutinee has no unresolved type arguments 
    * and is a "final type", meaning final + invariant in all type parameters. 
    */ 

en cuenta que ninguno no es definitivo, por ejemplo. ¿Yo se, verdad?

Si usted alguna vez de scalac -Ypatmat-depuración, el comentario aquí podría ayudar:

https://github.com/scala/scala/pull/650

La accesibilidad es casi al alcance:

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

Pero no veo cualquier promesa sobre lo que algún día podría ser advertible. Por razones de rendimiento? También se podría decir, ¿por qué debería advertir sobre un ejemplo de [Foo [_]]?

Por ahora, las secciones de especificación 8.2 - 8.4 motivan por qué la coincidencia con Foo [a] es interesante (debido a los límites que adquiere). Creo que leeré eso de nuevo. Después de un café

trait Foo[+A] 
final class Fuzz[+A] extends Foo[A] 
final object Fooz extends Foo[Nothing] 
object Futz extends Foo[Nothing] 

//error 
Fooz match { 
    case x: List[_] => println("A") 
    case _ => println("B") 
} 
//no error 
Futz match { ... } 
+0

Agradable, pensé que sería una rareza con el patrón de matcher pero no pude verlo anoche :-) – timothy

Cuestiones relacionadas