2016-05-13 7 views
1

スカラーでのパターンマッチングで、以下のような現象を引き起こすことはできません。私はprintln(typesPattern(Map("a"→10)))を以下に機能上呼び出すと、私は私が持っている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)スカラ+パターンマッチング+文字列オートボックス

最初の質問は、「MAP [ストリング]> intは] MAP [INTと一致なっている理由で次のエラーを取得する

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 

    } 
} 

INT]? "の場合は、MAP[_,_]と一致する必要があります。

興味深いことにIは、パターンマッチングコードを編集して、地図とプリントキーと値のペアからタプルを抽出するコードを取り出すとき

`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 

     } 
    }` 

今のように同じ呼び出し以前println(typesPattern(Map("a"→10)))が行う一致MAP [INT、INT]問題なく、サイズを印刷します。

Map[Int,Int] 
    1 

2番目の質問 「WHY SCALAは問題なく(私はまだだろうか?)MAP [INT-> INT]でMAPを[ストリング]> INT]一致させることができますTHIS TIME?

答えて

1

この問題は、ジェネリック型消去の起こる実行時に任意の種類のMap差がないパターンは、まず適切なケースで一致した理由です

簡単なスニペットは、それをチェックするために:。。。

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

私はそれを逃しました。それは応答のために私の質問に感謝します。 – Gurupraveen

0

タイプ消去のためです。ジェネリック型の使用法は、型情報を保持しないため、句には使用しません。従ってMAP[String->Int]Mapに相当します。そのため、MAP[String->Int]MAP[Int->Int]と一致します。

2

おそらく、コンパイラがあなたに与える警告を見てみるのですか?

<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; 

は実際には、これらの行の両方:地図上一致するすべての3本のラインが等価であるため、

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

は、少なくともそのパターンは同じものにマッチします、到達不能です。

実行時には、汎用タイプはありません。消去されるので、Map[A, B]はちょうどMapです。彼らは順番

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

でテストされているように、マップをマッチングあなたの唯一のケースでは、彼らはあなただけあればキャストますので、Intのようにそれらを処理する値を使用しようとする場合にのみ、あなたはClassCastExceptionを取得し、最初の1でありますそれらを使用しようとします。 sizeをチェックすることは、その値のタイプに依存しません。

0

パターンマッチングを使用する代わりに、implicitsと型クラスのメカニズムを使用する方が簡単でしょうか?

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) 
} 
関連する問題