如何解决在scala宏中,如何在编译时提升一个对象并在quasiquote中使用它?
以下代码片段是来自 Thoughtworks 项目的简短 scala 宏包定义:
private[SelfType] final class Macros(val c: whiteBox.Context) {
import c.universe._
def apply[A: WeakTypeTag]: Tree = {
val a = weakTypeOf[A]
val selfTypes: List[Type] = {
val selfTypeBuilder = List.newBuilder[Type]
def buildSelfTypes(t: Type): Unit = {
val dealiased = t.dealias
dealiased match {
case RefinedType(superTypes,refinedScope) =>
superTypes.foreach(buildSelfTypes)
case typeRef: TypeRef =>
val symbol = dealiased.typeSymbol
if (symbol.isClass) {
selfTypeBuilder += symbol.asClass.selfType.asSeenFrom(dealiased,symbol)
}
case _ =>
}
}
buildSelfTypes(a)
selfTypeBuilder.result()
}
val out = selfTypes match {
case Nil =>
deFinitions.AnyTpe
case _ =>
internal.refinedType(selfTypes,c.internal.enclosingOwner)
}
q"_root_.com.thoughtworks.feature.SelfType.make[$a,$out]"
}
}
作为准引用的最后一行似乎包含很多样板文本:
q"_root_.com.thoughtworks.feature.SelfType.make[$a,$out]"
假设这个宏包是作为家族多态设计模式的一部分在特征内定义的:没有确定性的q"_root_.com.thoughtworks.feature.SelfType.make[$a,$out]"
,它必须从宏包的对象变量vvv
派生编译的时候。如何使用此变量使准引用更短且更具适应性?
可能有多种方法来实现这一点(例如,对于每个实现,为 SelfType
对象定义一个 Liftable)。但这更像是样板。我正在寻找最短的解决方案。理想情况下,是这样的:
val sym = Term(vvv)
q"$sym.make[$a,$out]"
解决方法
如果您有静态引用(例如导入类型/伴随),您可以:
q"${symbolOf[SelfType.type]}.make[$a,$out]"
如果您有 symbolOf[A].companion
但没有关于它的同伴的信息,您也可以使用 A: WeakTypeTag
。如果编译器不认为 object A
是 class A
找到我的第一个解决方案:
val name = SelfTypes.getClass.getCanonicalName.stripSuffix("$")
val tree = c.parse(name)
q"$tree.make[$a,$out]"
不确定这是否是最有效或最惯用的解决方案,我将问题搁置一段时间
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。