scala - 是否可以集成 Cake-Pattern 和宏?

标签 scala macros self-type scala-2.10 cake-pattern

我必须在使用蛋糕模式的项目中集成一些宏。除了其他优势之外,这种模式使我们能够避免大量进口,因此我们希望保留它。现在,我们面临着一些我们在主干之外测试的实验性宏的问题。首先,让我们展示一个名为 Cake 的虚拟系统:

trait APiece {
  class A
}

trait BPiece { this: APiece => 
  def aMacro(a: A): Unit = () /* macro ??? */
}

trait CPiece { this: APiece with BPiece =>
  def aMacroInvoker = aMacro(new A)
}

class Cake { this: APiece with BPiece with CPiece => }

APiece定义了一个类,BPiece应该是一个使用APiece定义的类的宏,最后CPiece调用该宏。我说 BPiece 应该是一个宏,因为我无法为其编写实现代码。我尝试了多种方法,但总是崩溃并出现以下错误:

"macro implementation must be in statically accessible object"

阅读macros code人们可以猜测有必要将宏包含在静态模块中。有没有办法部署使用系统结构的宏?

最佳答案

幸运的是,您的问题有一个简单的解决方案。

但首先,让我回顾一下。在第一个原型(prototype)中,宏的定义如下: def macro aMacro(a: A): Unit = ... 。我们在准备 SIP 时取得的重大突破之一是将宏定义(宏的公共(public)面)和宏实现(托管宏逻辑的树形转换器)分开。我花了一段时间才意识到这有多酷,但现在每次我编写宏声明时我都会欣喜若狂。

那么,回到你的问题。当然,宏实现必须是静态可访问的(否则,编译器将无法在编译期间加载和调用它们)。然而宏定义没有这个限制,所以你可以这样写定义:

trait BPiece { this: APiece => 
  def aMacro(a: A): Unit = macro Macros.aMacro
}

从定义中引用的宏实现可以放入您希望的任何对象中,甚至可以放入不同的编译单元中。

唯一缺少的一 block 拼图是我们如何引用 A从实现来看,因为A是在蛋糕内部定义的。最简单的方法是制作 aMacro泛型并依赖类型推断:

(更新:要使该示例在 2.10.0-M7 中运行,您需要将 c.TypeTag 替换为 c.AbsTypeTag;要使该示例在 2.10.0-RC1 中运行,需要将 c.AbsTypeTag 替换为c.WeakTypeTag)

trait BPiece { this: APiece =>
  def aMacro[A](a: A): Unit = macro Macros.aMacro[A]
}

object Macros {
  def aMacro[A: c.TypeTag](c: Context)(a: c.Expr[A]): c.Expr[Unit] = c.literalUnit
}

这不会让你使用reify不过,因为对于宏实现 A只是一个没有任何成员的类型参数。如果您想从宏中返回特定于蛋糕的内容,也会出现问题,但让我们在出现问题时处理它们。如果需要,请提交后续问题。

关于scala - 是否可以集成 Cake-Pattern 和宏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11247766/

相关文章:

scala - 隐式<:<如何帮助查找类型参数

python - 将软件转换为 FPGA 的 VHDL/Verilog 的更好平台

c - C 中未声明的宏

scala - 使用类型成员作为自身类型

scala - Scala 构造说明

scala - 折叠具有未知类型的 HList

java - clojure/scala 互操作?

visual-studio - 通过DTE获取项目TargetPath的宏值

c++ - 如何在不使用宏的情况下在宏中创建条件

Java自类型方法: cannot safely cast to actual type