2016-05-13 17 views
1

Ich melde ein Feature, das seltsam klingt und das folgende Verhalten bei der Mustererkennung in scala nicht nachvollziehen kann.Scala + Mustererkennung + String Autoboxing

def typesPattern(x:Any)= x match{ 
    case s:String⇒ s.length 
    case n:Map[Int,Int]⇒println("Map[Int,Int]");var a = n.iterator.next();println(a._1);println(a._2);n.size;  
    case n:Map[a,b]⇒println("Map[a,b]");n.size;  
    case m:Map[_,_]⇒ m.size 
    case _ ⇒ -1 

    } 
} 

Wenn ich oben Funktion aufrufen mit println(typesPattern(Map("a"→10))) folgenden i Fehler Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer at scala.runtime.BoxesRunTime.unboxToInt(BoxesRunTime.java:101) at scala.Tuple2._1$mcI$sp(Tuple2.scala:20)

Erste Frage folgende erhalten, die ich ist haben "WARUM MAP [String-> Int] mit MAP immer abgestimmt [INT, INT]? ", sollte es eher mit MAP[_,_] übereinstimmen.

Interessanterweise, wenn ich den Pattern-Matching-Code bearbeiten und den Code herausnimmt, die Tupel Auszüge aus Karte und Druck Schlüssel-Wert-Paar

`def typesPattern(x:Any)= x match{ 
     case s:String⇒ s.length 
     case n:Map[Int,Int]⇒println("Map[Int,Int]");n.size;  
     case n:Map[a,b]⇒println("Map[a,b]");n.size;  
     case m:Map[_,_]⇒ m.size 
     case _ ⇒ -1 

     } 
    }` 

Nun ist der gleiche Aufruf wie früher println(typesPattern(Map("a"→10))) überein MAP [INT, INT] ohne Probleme und druckt die Größe.

Map[Int,Int] 
    1 

Zweite Frage „WARUM DIESES MAL SCALA IST MÖGLICH MAP ZUBRINGEN [String-> INT] mit MAP [INT> INT] (was ich noch fragen, wie?) Ohne Probleme?

Antwort

1

Dieses Problem tritt wegen Generika Typ Löschung In Laufzeit gibt es keinen Unterschied zwischen Map von irgendwelchen Typen Deshalb zunächst geeignetem Fall passen Muster

Einfache Schnipsel es zu überprüfen:...

List[String]().isInstanceOf[List[String]] // true 
List[String]().isInstanceOf[List[Integer]] // true 
+0

Ich habe es verpasst. Es beantwortet meine Frage danke für die Antwort. – Gurupraveen

0

Es ist wegen der Art Löschung. Die Verwendung generischer Typen ist in Fallklauseln nicht sinnvoll, da sie keine Typinformationen enthält. So entspricht MAP[String->Int]Map. Deshalb passen MAP[String->Int] mit MAP[Int->Int].

2

Sie haben vielleicht versucht, auf Warnungen Compiler sehen Sie?

<console>:12: warning: non-variable type argument Int in type pattern scala.collection.immutable.Map[Int,Int] (the underlying of Map[Int,Int]) is unchecked since it is eliminated by erasure 
     case n:Map[Int,Int]⇒println("Map[Int,Int]");var a = n.iterator.next();println(a._1);println(a._2);n.size; 
      ^
<console>:13: warning: unreachable code 
     case n:Map[a,b]⇒println("Map[a,b]");n.size; 

Eigentlich diese beiden Zeilen:

case n:Map[a,b]⇒println("Map[a,b]");n.size;  
    case m:Map[_,_]⇒ m.size 

sind nicht erreichbar, weil alle drei Linien, die auf der Karte übereinstimmen äquivalent sind, zumindest ihre Muster die gleichen Dinge entsprechen.

In der Laufzeit gibt es keine generischen Typen, sie sind gelöscht, so Map[A, B] ist nur ein Map. So Ihre einzige Fall, die Karte passend ist die erste, da sie

um getestet
case n:Map[Int,Int]⇒println("Map[Int,Int]");var a = n.iterator.next();println(a._1);println(a._2);n.size;  

Sie erhalten nur eine ClassCastException, wenn Sie versuchen, die Werte zu verwenden, um sie wie ein Int zu behandeln, weil sie nur, wenn Sie werfen bekommen versuche sie zu benutzen. Die Überprüfung von size hängt nicht vom Typ seiner Werte ab.

0

Wäre es nicht viel einfacher, wenn Sie anstatt Muster zu verwenden, verwenden Sie stattdessen implicits und Typ Klassen Mechanismus?

trait TypePattern[A,B] { 
    def pattern(a: A):B 
} 

implicit object stringPattern extends TypePattern[String,Int] { 
    override def pattern(a: String): Int = a.length 
} 

implicit object mapIntIntPattern extends TypePattern[Map[Int, Int],Int] { 
    override def pattern(n: Map[Int, Int]): Int = { 
    println("Map[Int,Int]") 
    var a = n.iterator.next() 
    println(a._1) 
    println(a._2) 
    n.size 
    } 
} 

implicit object mapAnyPattern extends TypePattern[Map[Any, Any],Int] { 
    override def pattern(a: Map[Any, Any]): Int = { 
    println("Map[a,b]") 
    a.size 
    } 
} 

def pattern[A,B](x: A)(implicit typePattern: TypePattern[A,B]): B = { 
    typePattern.pattern(x) 
}