如何在Scala宏中的箭头关联树(`x-> y`)上匹配?

时间:2014-07-09 18:47:55

标签: scala macros scala-quasiquotes

我想在Scala宏中对x -> y操作的树进行模式匹配。我正在针对Scala 2.10.4(使用Macro Paradise)和Scala 2.11.x进行交叉编译。我尝试了以下模式,但都没有效果:

arrowTree match {
  case q"$x -> $y"                                            => ???
  case q"scala.Predef.ArrowAssoc[${_}, ${_}]($x).->$y"        => ???
  case q"_root_.scala.Predef.ArrowAssoc[${_}, ${_}]($x).->$y" => ???
  case q"_root_.scala.Predef.ArrowAssoc($x).->$y"             => ???
}

哪种模式可以使这种匹配同时适用于2.10.4和2.11.x?

1 个答案:

答案 0 :(得分:2)

在一个完美的世界里,你绝对希望第一个匹配,但并不是那么简单。

每当您在Scala中编写foo -> bar时,您都会有效地调用foo.->(bar)之类的方法。当typechecker试图找到一个名为->的方法时,它会失败,并开始寻找可能将该方法添加到foo的任何含义,并且它通常会找到Predef.ArrowAssoc,将原始表达式转换为scala.this.Predef.ArrowAssoc[Int](1).->[Int](2)

要匹配此项,您可以使用以下模式:

case q"scala.this.Predef.ArrowAssoc[$_]($foo).->[$_]($bar)" =>

这里我们将通配符放在类型参数位置,因为我们现在不关心它们。

在2.10上,模式会略有不同,因为当时隐含的名称不同:

case q"scala.this.Predef.any2ArrowAssoc[${_}]($foo).->[${_}]($bar)" =>

这里的另一个区别是需要在通配符周围使用花括号。 2.10不支持字符串插值器中的$_语法。