使用 Witness 提取类型标签
Extracting type tag with Witness
我正在 运行 对 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
-tricks 都没有呈现。隐式 Witness.Aux[TypeTag]
来自
implicit def apply[T]: Witness.Aux[T] = macro SingletonTypeMacros.materializeImpl[T]
它实际上是如何工作的?是编译器优化了那些方法调用吗?或者这是通过 macro
?
完成的
在方法调用getTaggedValue("xxx" ->> 32)
中,结果类型是单例类型"xxx"
。 Scala 2.12 编译器原则上会将每个具有单例类型的表达式内联到伴随值(由于缺乏更好的术语,"xxx"
类型的 "value" 是字符串 "xxx"
)。所以在这种情况下,整个表达式 getTaggedValue("xxx" ->> 32)
及其包含的所有内容,如构造 "xxx" ->> 32
和调用隐式 Witness
,都将被删除为简单值 "xxx"
.
Scala 2.13 对单例类型进行了一些修改,使它们成为语言中的第一个 class 公民,并且在该过程中,内联变得不那么激进了。因为如果您要向 getTaggedValue
方法添加副作用,您会发现这种内联并不总是安全的。这意味着当您使用 Scala 2.13 进行编译时,您 将 在字节码中看到诸如 getTaggedValue
和 Witness.mkWitness
之类的调用。
我正在 运行 对 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
-tricks 都没有呈现。隐式 Witness.Aux[TypeTag]
来自
implicit def apply[T]: Witness.Aux[T] = macro SingletonTypeMacros.materializeImpl[T]
它实际上是如何工作的?是编译器优化了那些方法调用吗?或者这是通过 macro
?
在方法调用getTaggedValue("xxx" ->> 32)
中,结果类型是单例类型"xxx"
。 Scala 2.12 编译器原则上会将每个具有单例类型的表达式内联到伴随值(由于缺乏更好的术语,"xxx"
类型的 "value" 是字符串 "xxx"
)。所以在这种情况下,整个表达式 getTaggedValue("xxx" ->> 32)
及其包含的所有内容,如构造 "xxx" ->> 32
和调用隐式 Witness
,都将被删除为简单值 "xxx"
.
Scala 2.13 对单例类型进行了一些修改,使它们成为语言中的第一个 class 公民,并且在该过程中,内联变得不那么激进了。因为如果您要向 getTaggedValue
方法添加副作用,您会发现这种内联并不总是安全的。这意味着当您使用 Scala 2.13 进行编译时,您 将 在字节码中看到诸如 getTaggedValue
和 Witness.mkWitness
之类的调用。