【问题标题】:what should a scala implicit macro have to return to tell the compiler "forget my result, continue your search"scala 隐式宏应该返回什么来告诉编译器“忘记我的结果,继续你的搜索”
【发布时间】:2020-10-26 23:57:01
【问题描述】:

我有一个带有贪婪签名的隐式宏

implicit def materializeHelper[C <: Any]: Helper[C] = macro materializeHelperImpl[C]

def materializeHelperImpl[C <: Any: ctx.WeakTypeTag](ctx: blackbox.Context): ctx.Expr[Helper[C]] = ???

根据它的签名,它会为任何 C 实现 Helper[C]。但身体更加挑剔。它只接受 Cs 是密封的特征。 宏应该返回什么来告诉编译器“忘记我的结果,继续你的隐式搜索,就好像我不存在一样”?

目前我正在返回一个空块 (q""),这并不理想,因为当所述隐式用作中间规则时,编译器会具体化 null。例如,在以下行中,当宏返回空 (q"") 时,helper 参数设置为 null。

implicit def parser[C <: Any](implicit helper: Helper[C]): Parser[C] = new Parser[C](helper)

我的意图是,在C 不是密封特征的情况下,编译器会丢弃前面提到的隐式并继续搜索另一个更具体的隐式值。

【问题讨论】:

  • *.com/questions/64122310/… 这能回答你的问题吗?
  • @DmytroMitin 是的,我想是的。那么,如果我将宏类型更改为白框,我应该中止它还是返回一个空块(q"")也可以?
  • @DmytroMitin 请把您的评论作为答案,以便我检查。非常感谢。
  • 显然,当宏类型为白色时,返回一个空块也告诉编译器丢弃该值。
  • 惯用方法是使用自定义错误消息调用c.abort。抛出异常,调用c.error,返回EmptyTree(在这种情况下它只是不进行类型检查,但最好有明确的编译错误消息)也是可能的,尽管它们看起来不那么惯用。

标签: scala implicit scala-macros


【解决方案1】:

你没有让你的宏实现类型类Helper whitebox。

通常隐式宏应该是白盒。

如果黑盒宏(甚至是隐式黑盒宏)抛出异常 那么在编译主代码时就会出现编译错误。如果一个 whitebox 隐式宏在编译期间引发异常 隐含的主代码将从候选者中静默删除。

Implicit macro. Default implicit value. How?

https://docs.scala-lang.org/overviews/macros/blackbox-whitebox.html

使用自定义错误消息调用c.abort 更为惯用。抛出异常,调用c.error,返回EmptyTree(在这种情况下它只是不进行类型检查)也是可能的,尽管它们看起来不那么惯用(最好有明确的编译错误消息)。

【讨论】: