首页 > 解决方案 > 使用 Scala3 宏构建动态表达式

问题描述

在Scala2的宏中,可以通过Context.parse等动态构造表达式。

  def generateExpr[T: c.WeakTypeTag](target: C#Symbol): C#Expr[T] = {
    if (target.isModule) {
      c.Expr[T](c.parse(target.fullName))
    } else {
      c.Expr[T] {
        c.parse(
          s"""new ${target.fullName}(${
            val a = target.asClass.primaryConstructor.asMethod
            val b = a.paramLists
            target.asClass.primaryConstructor.asMethod.paramLists
              .collect {
                case curry if !curry.exists(_.isImplicit) =>
                  curry.map { param => s"inject[${param.typeSignature.toString}]" }.mkString(",")
              }
              .mkString(")(")
          }) with MixIn"""
        )
      }
    }
  }

即使预组合语法文字引用了不在当前类路径中的符号,如果它可以在调用宏的模块中解析,编译也会成功。

但是,已发布的 Scala3 中并没有这样的功能。

我的目标是使用

  1. 使用宏来引用不在模块类路径中的符号。
  2. 我想new $T(???) with Trait从类型信息中使用。

这些不再可行了吗?

=====

https://github.com/lampepfl/dotty/discussions/12590

正如本期提到的,将可变长度参数部署到 Trees 也是未知的。这些将与动态 AST 构造相关。

标签: scalascala-macrosscala-3

解决方案


这些是我们明确不想支持的用例,因为它们会导致语言碎片化,宏支持许多可能的方言。我确信这有很好的用例,但总的来说,我认为允许这样做会对整个语言生态系统造成损害。

https://contributors.scala-lang.org/t/compatibility-required-for-migration-from-scala2-macro/5100/2?u=giiita


推荐阅读