如何解释这些模式匹配的例子?
How to explain these pattern matching examples?
我在FSM中写了一些事件,在模式匹配时发现了一些我无法解释的东西。我认为以下是完全合法的,即我可以向该演员发送一条消息,该消息是 vector[A] 或 vector[B]。
when(State) {
case Event(content: Vector[A], _) => {
println("matched A")
stay
}
case Event(content: Vector[B], _) => {
println("matched B")
stay
}
}
但是,
如果我向演员发送 vector[B] 消息,它会导致
java.lang.ClassCastException: B cannot be cast to A
所以基本上它会尝试匹配第一个事件,尽管下一个会匹配。
我试图制作一个更简单的模式匹配示例;
object Pattern extends App {
val n = Vector(1,2,3)
val s = Vector("S", "S", "S")
n match{
case e:Vector[String] => println("matched string")
case v:Vector[Int] => println("matched int")
}
}
这实际上是不合法的;
Error:(8, 12) pattern type is incompatible with expected type;
found : Vector[String]
required: scala.collection.immutable.Vector[Int]
case e:Vector[String] => println("matched string")
但是,如果我执行以下转换,我可以 运行 我的代码;
object Pattern extends App {
val n = Vector(1,2,3).asInstanceOf[Vector[Any]]
val s = Vector("S", "S", "S")
n match{
case e:Vector[String] => println(n(0).getClass)
case v:Vector[Int] => println("matched int")
}
}
然后我觉得奇怪的是,我显然说 Any 可以匹配字符串,但打印出来的是 java.lang.Integer。所以我应该把它想象成我有一个 vector[Int],我说它是一个 Vector[Any],因为 Vector[Any] 可能是一个 Vector[String],它匹配那个模式,而且因为它确实是一个 vector[ Int] 我掩码为 Vector[Any] 打印也很好。
有人可以解释这些模式匹配观察结果吗?
我应该如何设置消息以便我的状态可以同时处理 Vector[A] 和 Vector[B] 的消息?
由于 jvm 类型信息的类型擦除在运行时会丢失,因此不直接支持这种模式匹配(与更高类型的模式匹配)。
以下是解决此问题的方法
相反,我建议您将向量包装在另一个容器中。
sealed trait Vectors
case class VectorString(vs: Vector[String]) extends Vectors
case class VectorInt(vi: Vector[Int]) extends Vectors
def doStuff(v: Vectors) = v match {
case VectorString(vs) => //be sure that vs is Vector[String]
case VectorInt(vi) =>
}
在 Scala 中模式匹配泛型类型的方法
使用TypeTag
import scala.reflect.runtime.universe._
def handle[A: TypeTag](a: A): Unit =
typeOf[A] match {
case t if t =:= typeOf[List[String]] =>
// list is a string list
val r = a.asInstanceOf[List[String]].map(_.length).sum
println("strings: " + r)
case t if t =:= typeOf[List[Int]] =>
// list is an int list
val r = a.asInstanceOf[List[Int]].sum
println("ints: " + r)
case _ => // ignore rest
}
val ints: List[Int] = Nil
handle(List("hello", "world")) // output: "strings: 10"
handle(List(1, 2, 3)) // output: "ints: 6"
handle(ints) // output: "ints: 0" it works!
我在FSM中写了一些事件,在模式匹配时发现了一些我无法解释的东西。我认为以下是完全合法的,即我可以向该演员发送一条消息,该消息是 vector[A] 或 vector[B]。
when(State) {
case Event(content: Vector[A], _) => {
println("matched A")
stay
}
case Event(content: Vector[B], _) => {
println("matched B")
stay
}
}
但是, 如果我向演员发送 vector[B] 消息,它会导致
java.lang.ClassCastException: B cannot be cast to A
所以基本上它会尝试匹配第一个事件,尽管下一个会匹配。
我试图制作一个更简单的模式匹配示例;
object Pattern extends App {
val n = Vector(1,2,3)
val s = Vector("S", "S", "S")
n match{
case e:Vector[String] => println("matched string")
case v:Vector[Int] => println("matched int")
}
}
这实际上是不合法的;
Error:(8, 12) pattern type is incompatible with expected type;
found : Vector[String]
required: scala.collection.immutable.Vector[Int]
case e:Vector[String] => println("matched string")
但是,如果我执行以下转换,我可以 运行 我的代码;
object Pattern extends App {
val n = Vector(1,2,3).asInstanceOf[Vector[Any]]
val s = Vector("S", "S", "S")
n match{
case e:Vector[String] => println(n(0).getClass)
case v:Vector[Int] => println("matched int")
}
}
然后我觉得奇怪的是,我显然说 Any 可以匹配字符串,但打印出来的是 java.lang.Integer。所以我应该把它想象成我有一个 vector[Int],我说它是一个 Vector[Any],因为 Vector[Any] 可能是一个 Vector[String],它匹配那个模式,而且因为它确实是一个 vector[ Int] 我掩码为 Vector[Any] 打印也很好。
有人可以解释这些模式匹配观察结果吗?
我应该如何设置消息以便我的状态可以同时处理 Vector[A] 和 Vector[B] 的消息?
由于 jvm 类型信息的类型擦除在运行时会丢失,因此不直接支持这种模式匹配(与更高类型的模式匹配)。
以下是解决此问题的方法
相反,我建议您将向量包装在另一个容器中。
sealed trait Vectors
case class VectorString(vs: Vector[String]) extends Vectors
case class VectorInt(vi: Vector[Int]) extends Vectors
def doStuff(v: Vectors) = v match {
case VectorString(vs) => //be sure that vs is Vector[String]
case VectorInt(vi) =>
}
在 Scala 中模式匹配泛型类型的方法
使用TypeTag
import scala.reflect.runtime.universe._
def handle[A: TypeTag](a: A): Unit =
typeOf[A] match {
case t if t =:= typeOf[List[String]] =>
// list is a string list
val r = a.asInstanceOf[List[String]].map(_.length).sum
println("strings: " + r)
case t if t =:= typeOf[List[Int]] =>
// list is an int list
val r = a.asInstanceOf[List[Int]].sum
println("ints: " + r)
case _ => // ignore rest
}
val ints: List[Int] = Nil
handle(List("hello", "world")) // output: "strings: 10"
handle(List(1, 2, 3)) // output: "ints: 6"
handle(ints) // output: "ints: 0" it works!