Scala+;模式匹配&x2B;字符串自动装箱
我报告的一个功能听起来很奇怪,无法用scala中的模式匹配来解释以下行为Scala+;模式匹配&x2B;字符串自动装箱,scala,pattern-matching,Scala,Pattern Matching,我报告的一个功能听起来很奇怪,无法用scala中的模式匹配来解释以下行为 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
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
}
}
当我用下面的println(typesPattern(Map(“a”)调用上述函数时→10) )
我在线程“main”java.lang.ClassCastException中得到以下错误异常:java.lang.String不能转换为java.lang.Integer
在scala.runtime.BoxesRunTime.unextoint(BoxesRunTime.java:101)中
在scala.Tuple2.\u 1$mcI$sp(Tuple2.scala:20)
我的第一个问题是“为什么MAP[String->Int]与MAP[Int,Int]匹配?”,它应该与MAP[\uu,\u]
匹配
有趣的是,当我编辑模式匹配代码并取出从映射中提取元组并打印键和值对的代码时
`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) )
不匹配映射[INT,INT],没有问题,并打印大小
Map[Int,Int]
1
第二个问题
“为什么这次SCALA能够将MAP[String->INT]与MAP[INT->INT](我仍然想知道如何匹配?)匹配而没有问题?这个问题是由于泛型类型擦除造成的。在运行时,任何类型的
MAP
之间都没有区别。这就是为什么模式在第一个合适的情况下匹配
检查它的简单代码段:
List[String]().isInstanceOf[List[String]] // true
List[String]().isInstanceOf[List[Integer]] // true
这是因为类型擦除。泛型类型在case子句中没有用处,因为它不保留类型信息。因此
MAP[String->Int]
相当于MAP
。这就是为什么MAP[String->Int]
与MAP[Int->Int]
匹配您可能试图查看编译器给您的警告
<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;
是不可到达的,因为地图上匹配的所有三条线都是等效的,至少它们的模式将匹配相同的东西
在运行时没有泛型类型,它们会被擦除,因此Map[A,B]
只是一个Map
。因此,与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
,因为只有当您尝试使用它们时,它们才会被强制转换。检查size
并不取决于其值的类型。如果不尝试使用模式匹配,而是使用隐式和类型cla,则不会容易得多安全机制
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)
}
我错过了。它确实回答了我的问题。谢谢你的回答。
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)
}