下面的代码片段是一个来自 thinkworks 项目的简短 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]"
}
}
最后一行作为 quasiquote 似乎包含很多样板文本:
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]"