[英]Calling a function with TypeTag recursively
I'm playing with Scala TypeTag. 我在玩Scala TypeTag。 I want to recursively call a function with a TypeTag parameter. 我想用TypeTag参数递归调用一个函数。 Here is a simplified example of what I'm trying to do: 这是我要执行的操作的简化示例:
import scala.reflect.runtime.universe._
object TypeTagTest extends App {
def intValue[T](value: T)(implicit tag: TypeTag[T]): Int = {
tag.tpe match {
// integer
case intType if intType <:< typeOf[Int] =>
value.asInstanceOf[Int]
// string
case stringType if stringType <:< typeOf[String] =>
value.asInstanceOf[String].toInt
// option of either string or integer
case optionType @ TypeRef(_, _, typeArg::Nil) if optionType <:< typeOf[Option[_]] =>
println(s"Unwrapped type is $typeArg")
val option = value.asInstanceOf[Option[_]]
option.map { optionValue =>
// how to pass the typeArg here?
intValue(optionValue)
}.getOrElse(0)
}
}
println(intValue(1))
println(intValue("1"))
println(intValue(Some("1")))
}
This code compiles and runs: 该代码编译并运行:
1
1
Exception in thread "main" scala.MatchError: Any (of class scala.reflect.internal.Types$TypeRef$$anon$6)
at TypeTagTest$.intValue(TypeTagTest.scala:7)
at TypeTagTest$$anonfun$intValue$2.apply(TypeTagTest.scala:19)
at TypeTagTest$$anonfun$intValue$2.apply(TypeTagTest.scala:18)
at scala.Option.map(Option.scala:145)
Couple of questions: 几个问题:
It's not a recursion problem - your "Unwrapped type..." line never prints. 这不是递归问题-您的“ Unwrapped type ...”行永远不会打印。 I suspect the problem is that optionType
, in this case Some[String]
, is not a strict subtype of Option[_]
which expands to Option[A] forSome {type A}
. 我怀疑问题在于,在这种情况下, Some[String]
optionType
不是Option[_]
Option[A] forSome {type A}
,后者会扩展为Option[A] forSome {type A}
。
In this specific instance perhaps you want to test whether optionType <:< Option[Any]
, since Option
is covariant? 在这种特定情况下,您可能想测试optionType <:< Option[Any]
,因为Option
是协变的? Or perhaps you could check that the first argument of the TypeRef
is Option
. 或者,您可以检查TypeRef
的第一个参数是否为Option
。
Once you've fixed that, I don't think it's possible to obtain the TypeTag
for a parameter since they're always generated by the compiler, but since you're only using the Type
you can make the method work with those instead: 修复此问题后,我认为无法获取参数的TypeTag
,因为它们始终由编译器生成,但是由于仅使用Type
,因此可以使该方法与那些对象一起使用:
def intValueInner(value: Any, tpe: Type) = tpe match {
...
case optionType @ TypeRef(_, _, typeArg::Nil) if optionType <:< typeOf[Option[Any]] =>
value.asInstanceOf[Option[_]].map(v => intValueInner(v, typeArg)).getOrElse(0)
}
def intValue[T: TypeTag](t: T) = intValueInner(t, typeOf[T])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.