使用见证提取类型标记



我正在用Witness进行一些实验,现在试图了解它是如何工作的。请考虑以下示例:

import shapeless.syntax.singleton._
import shapeless.labelled.FieldType
import shapeless.Witness
def main(args : Array[String]): Unit = {
println(getTaggedValue("xxx" ->> 32))
println(getTaggedValue("yyy" ->> 44))
}
def getTaggedValue[TypeTag, Value](kt: FieldType[TypeTag, Value])
(implicit witness: Witness.Aux[TypeTag]): TypeTag = witness.value

正如预期的那样,程序打印

xxx
yyy

我试图了解这些xxx值和yyy值是如何获得的,并打印了main函数的实际字节码:

62: getstatic     #69                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
65: ldc           #71                 // String xxx
67: invokevirtual #75                 // Method scala/Predef$.println:(Ljava/lang/Object;)V
70: getstatic     #69                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
73: ldc           #77                 // String yyy
75: invokevirtual #75                 // Method scala/Predef$.println:(Ljava/lang/Object;)V

可以看出,所有这些Witness技巧都没有出现。隐含的Witness.Aux[TypeTag]来自implicit def apply[T]: Witness.Aux[T] = macro SingletonTypeMacros.materializeImpl[T]

它实际上是如何工作的?是编译器优化了这些方法调用吗?或者这是通过macro完成的?

在方法调用getTaggedValue("xxx" ->> 32)中,结果类型是单例类型"xxx"。Scala 2.12 编译器原则上会将每个具有单例类型的表达式内联到随附的值(由于缺乏更好的术语,类型"xxx"的"值"是字符串"xxx"(。所以在这种情况下,整个表达式getTaggedValue("xxx" ->> 32)及其包含的所有内容,如构造"xxx" ->> 32和调用隐式Witness,都将被擦除为简单值"xxx"

Scala 2.13 对单例类型进行了一些修改,使它们成为该语言中的一等公民,并且在此过程中内联变得不那么激进。因为如果您将副作用添加到getTaggedValue方法中,您会发现此内联并不总是安全的。这意味着当你使用 Scala 2.13 编译时,你会在字节码中看到getTaggedValueWitness.mkWitness等调用。

相关内容

  • 没有找到相关文章

最新更新