【问题标题】:How do I splice symbols of various types in a quasiquote?如何在准引号中拼接各种类型的符号?
【发布时间】:2014-01-03 16:17:57
【问题描述】:

我正在开发一个宏,在它的实现中我得到了 weakTypeOf T 其中 T 是宏函数的类型参数。我想拼接信息,从这个具体类型的方法定义到一个新的类声明树。我无法获得类型参数的 AST(为了对其进行模式匹配),所以我必须绝对使用基于符号的 API。我的问题是如何在比缩进和成员选择更多的位置拼接符号?

例如要获取我所做的符号列表:

val methodDefs = tpe.declarations
.filter(decl => decl.isMethod && decl.isPublic && !decl.asMethod.isConstructor && !decl.isSynthetic)
.map(symb => symb.asMethod)

然后将信息拼接到 q 插值器,我想这样做:

val newdefs : List[Tree] = methodDefs.map(methodDef => { q"def ${methodDef.name}[..${methodDef.typeParams}](...${methodDef.paramss}): ${methodDef.returnType} = ???"})

根据符号如何拼接(described here (PDF)),我不能直接做这种拼接。实现这一目标的正确方法是什么?

【问题讨论】:

  • 我唯一能想到的就是手动创建对应类型和值参数的树。名称和类型可以拼接得很好,但是还不错。
  • 通过使用 Liftable,对吗?谢谢你:D(一点也不差,相反我觉得这个功能很有表现力!)
  • 好的,我想我明白了。无需升降。
  • 好吧,我确实认为在这个用例中事情会变得冗长,所以也许会更好,但我没有立即看到如何改进。
  • 这比我想象的要复杂得多:gist.github.com/xeno-by/8252596

标签: scala scala-macros scala-quasiquotes


【解决方案1】:

我想这样就足够了:

val newdefs = tpe
    .declarations
    .collect {
        case m: MethodSymbol if !m.isConstructor && m.typeParams.length > 0 => 
            val typeParams =  m.typeParams.map(TypeDef(_))
            val paramss = m.paramss.map(_.map(ValDef(_)))
            val returns = TypeTree(m.returnType)
            q"def ${m.name}[..${typeParams}](...${paramss}): ${returns} = ???"
    }.toList

【讨论】:

  • 是的,反射 API 中有一些 Symbol => 树工厂。你甚至可以说DefDef(m, q"???") 达到同样的效果。但是,它们都已被弃用,可能会在 2.11.0 中被删除 :)
  • 弃用的原因是符号给树的构造带来了很多棘手的问题,因此,只要有可能,我们希望摆脱使用它们的树 API。一些背景信息:groups.google.com/forum/#!topic/scala-internals/TtCTPlj_qcQ.
  • @EugeneBurmako 如果DefDef 现在已弃用,首选方法是什么?我似乎找不到任何直截了当的文档。 DefDef 的弃用只是说要导入 compat 或迁移。导入compat 时,系统会告诉您使用internal.defDef。目前尚不清楚还有什么其他方法可以在这里起作用。
  • internal.defDef 转发到与DefDef 使用的完全相同的功能。 internal 部分表示它是一个高级 API,如果您对编译器内部没有太多经验,则不应使用它。如果您对是否应该使用 internal 犹豫不决,请谨慎行事,并尝试使用 quasiquotes 来实现相同的目的。
  • 谢谢@EugeneBurmako,这很有道理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-04
  • 2011-08-03
  • 1970-01-01
  • 1970-01-01
  • 2011-08-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多