scala – 如何手动创建TypeTag?
我有兴趣手动创建一个TypeTag(从2.10M5开始):
object X { import reflect.runtime.universe._ def tt[A : TypeTag](a: A) = typeTag[A] // how to do this manually? val t = tt(List("")(_)) } scalac -Xprint:typer< file> .scala导致 package <empty> { object X extends scala.AnyRef { def <init>(): X.type = { X.super.<init>(); () }; import scala.reflect.runtime.`package`.universe._; def tt[A >: Nothing <: Any](a: A)(implicit evidence$1: reflect.runtime.universe.TypeTag[A]): reflect.runtime.universe.TypeTag[A] = scala.reflect.runtime.`package`.universe.typeTag[A](evidence$1); private[this] val t: reflect.runtime.universe.TypeTag[Int => String] = X.this.tt[Int => String](((x$1: Int) => immutable.this.List.apply[String]("").apply(x$1)))({ val $u: reflect.runtime.universe.type = scala.this.reflect.runtime.`package`.universe; val $m: $u.Mirror = scala.this.reflect.runtime.`package`.universe.runtimeMirror(this.getClass().getClassLoader()); $u.TypeTag.apply[Int => String]($m,{ final class $typecreator1 extends TypeCreator { def <init>(): $typecreator1 = { $typecreator1.super.<init>(); () }; def apply[U >: Nothing <: scala.reflect.base.Universe with Singleton]($m$untyped: scala.reflect.base.MirrorOf[U]): U#Type = { val $u: U = $m$untyped.universe; val $m: $u.Mirror = $m$untyped.asInstanceOf[$u.Mirror]; $u.TypeRef.apply($u.ThisType.apply($m.staticModule("scala").asModuleSymbol.moduleClass),$m.staticClass("scala.Function1"),scala.collection.immutable.List.apply[$u.Type]($m.staticClass("scala.Int").asTypeSymbol.asTypeConstructor,$m.staticClass("java.lang.String").asTypeSymbol.asTypeConstructor)) } }; new $typecreator1() }) }); <stable> <accessor> def t: reflect.runtime.universe.TypeTag[Int => String] = X.this.t } } 它似乎完全是编译器魔术,因为类型是硬编码的.不过有没有办法手动执行此操作? 解决方法
在M3中,您可以以非常简单的方式创建类型标记,例如:TypeTag [Int](TypeRef(< scala package>,< scala.Int>的符号,Nil)).它基本上意味着一旦创建了一个类型标记,它就会永远绑定到某个类加载器(即上面示例中用于加载scala.Int符号的类加载器).
当时很好,因为我们认为我们可以拥有一个适合所有类加载器的一体适用的镜像.这很方便,因为您可以隐式编写[TypeTag [T]],编译器将使用该全局镜像来实例化您请求的Type. 不幸的是,根据反馈,我们意识到这不会起作用,我们需要多个镜像 – 每个镜像都有自己的类加载器. 然后很明显类型标签需要灵活,因为一旦你隐式编写[TypeTag [T]],编译器就没有足够的信息你想要使用哪个类加载器.基本上有两种选择:1)使类型标记路径依赖于镜像(因此每次从编译器请求类型标记时都会强制显式提供镜像),2)将类型标记转换为类型工厂,能够在任何镜子中实例化自己长话短说,第一个选项没有用,所以我们就在这里. 因此,当前类型标签需要以非常简单的方式创建,如https://github.com/scala/scala/blob/master/src/library/scala/reflect/base/TypeTags.scala#L143中所述.您调用随附的TypeTag中定义的工厂方法并提供两个参数:1)默认镜像,其中将实例化类型标记,2)一个类型工厂,可以在任意镜像中实例化一个类型标记.这基本上就是编译器在你上面附带的打印输出中所做的. 为什么我打电话给这个环岛?因为要提供类型工厂,您需要手动子类化scala.reflect.base.TypeFactory类.这是Scala类型系统在函数和依赖类型方法之间的边界上的一个不幸的限制. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |