2012-09-09 12 views
5

Könnte jemand erklären, warum der folgende Code kompiliert?Scala Mustererkennung und Typ Rückschluss

Dies gibt mir eine (erwartete) Warnung über Typ löschen, aber es kompiliert noch. Ich erwartete, dass dies einen Typfehler verursacht, wie es tut, wenn ich auf "foo" statt Option("foo") übereinstimmte.

Danke!

+1

Sieht aus wie ein Fehler. Ich würde es melden. – sschaef

Antwort

2

Ich würde annehmen, dass der Compiler beide Option und List als Product behandelt, weshalb es kompiliert. Wie Sie sagen, wird die Warnung über das Löschen von Typen erwartet. Hier ist ein Beispiel, das ein anderes Produkt verwendet:

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") 
       ^

UPDATE w/r/t Fallklassen (wegen des Kommentars unten):

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

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

Es scheint, dass es nichts mit 'Produkt' zu tun hat. Ich habe 'Option (" foo ")' durch meine eigene Fallklasse ersetzt, die einzelne Parameter verwendet, und es gibt keinen Fehler. – ghik

+2

Errr, Fallklassen erweitern automatisch das Produkt. Siehe Antwort bearbeiten. – timothy

+1

Nun gut, aber es muss eigentlich keine Fallklasse sein. Übliche nicht-finale Klasse verursacht auch keinen Fehler. – ghik

0

Ich bemerkte, dass ein Fehler angezeigt wird, wenn die Klasse der Wert, den Sie übereinstimmen, wird als endgültig deklariert (und wir wissen, dass String endgültig ist). Ich weiß immer noch nicht, warum es keinen Fehler gibt.

4

Der Code kommentiert wird, also lassen Sie uns einen Moment Zeit nehmen, das genießen:

/** 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. 
    */ 

Beachten Sie, dass keine nicht endgültig ist, zum Beispiel. Ich weiß es schon gut?

Wenn Sie jemals scalac -Ypatmat-debug versuchen, den Kommentar hier helfen könnten:

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

Erreichbarkeits ist fast in Reichweite:

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

Aber ich sehe nicht, irgendwelche Versprechen darüber, was eines Tages vielleicht warnen könnte. Aus Leistungsgründen? Man könnte auch sagen, warum sollte es vor einer Instanz von [Foo [_]] warnen?

Vorerst motivieren die Spec-Abschnitte 8.2 - 8.4, warum das Matching gegen Foo [a] interessant ist (wegen der Grenzen a erwirbt). Ich denke, ich werde das nochmal lesen. Nach etwas Kaffee.

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

Schön, dachte, es wäre eine Eigenart mit dem Muster Matcher aber konnte es letzte Nacht nicht sehen :-) – timothy

Verwandte Themen