我有一个方法可以探索不同类函数的不同参数值。以前,我做了一些非类型安全的运行时检查,其中,擦除后,所有重要的是我使用的是Function2而不是Function3。我已经尝试使用ClassTags / TypeTag更安全了,但我仍然在为一个好的解决方案而苦苦挣扎。我原来的参考点是 tksfz回答:
How do I get around type erasure on Scala? Or, why can't I get the type parameter of my collections?
import reflect.ClassTag
def matchList[A: ClassTag](list: List[A]) = list match {
case strlist: List[String] => println("A list of strings!")
case intlist: List[Int] => println("A list of ints!")
case _ => println("Ok")
}
然而,我发现给定的片段没有用,两个案例都匹配一个字符串列表 - 答案可能是scala的不同版本(我使用2.10。 3)。
我找到了另一个例子,其中有人使用TypeTag给出了一个片段(我对类型标签类型之间的差异仍然有点模糊;我很高兴RTFM响应在这一点,只要它附有一个好的M到FR的链接)。
编辑:我之前的例子没有应用这些函数,因此产生警告的匹配部分毫无意义(正如第一个回答者指出的那样)。我已经更新了示例,以便更能代表我的实际问题。
package misc
import reflect.runtime.universe._
object CTDemo {
def main(args: Array[String]) = {
val f0v: Function2[Int, Double, String] = f0(_, _)
val f1v: Function2[Int, (Double, Double), String] = f1(_, _)
println(matchFunc(f0v))
println(matchFunc(f1v))
}
def f0(i: Int, p: Double) = {
s"output on $p doesn't matter"
}
def f1(i: Int, p: (Double, Double)) = {
s"output on $p doesn't matter"
}
def matchFunc[I: TypeTag, A: TypeTag, O: TypeTag](predFunc: Function2[I, A, O]) = {
predFunc match {
case fs: Function2[Int, Double, String] if(typeOf[A] <:< typeOf[Double]) => {
"Single-arg, result is: " + fs(1,2.0)
}
case ds: Function2[Int, (Double, Double), String] if(typeOf[A] <:< typeOf[(Double,Double)]) => {
"Double-arg, result is: " + ds(1,(2.0,3.0))
}
}
}
}
这种情况有效,但它仍会引发编译器警告。是否有一个简洁,&#34; asInstanceOf&#34; - 免费,无警告和线程安全的方式来检查函数的类型签名?如果有帮助,我愿意升级到scala 2.11。
答案 0 :(得分:2)
你的比赛没有做任何工作,所以只是
def matchFunc[I: TypeTag, A: TypeTag, O: TypeTag](predFunc: Function2[I, A, O]) = {
if (typeOf[A] <:< typeOf[Double]) {
"Single-arg"
} else if (typeOf[A] <:< typeOf[(Double,Double)]) {
"Double-arg"
}
}
另一个成语就是这样:
scala> def g[A: reflect.ClassTag](as: List[A]) = as match { case List(_: Int) => "I" }
g: [A](as: List[A])(implicit evidence$1: scala.reflect.ClassTag[A])String
scala> g(List(3))
res4: String = I
scala> g(List(3.0))
scala.MatchError: List(3.0) (of class scala.collection.immutable.$colon$colon)
at .g(<console>:7)
... 33 elided
也就是说,作为一个美化(虽然方便)isInstanceOf。
在Scala中,它是RTFS,其中S = spec或SIP。