在中缀位置的Scala无类型宏

时间:2013-03-06 17:07:33

标签: scala macros scala-macros

为了回应this question,我一直在使用宏天堂分支在Scala中实现Haskell风格的'where'表达式。该代码位于scala-where。我现在可以写下如下内容:

val result = where ( f1(1) * f2(2), {
  def f1(x : Int) = x + 1
  def f2(x : Int) = x + 2
})

然而,我真正想做的是能够在中缀位置调用它:

val result = ( f1(1) * f2(2)) where {
  def f1(x : Int) = x + 1
  def f2(x : Int) = x + 2
}

通常情况下,这种事情很容易,但我看不到如何使用宏调用。表达式(f1(1)* f2(2))将不会在宏应用程序之前键入,因此构建隐式值类的操作不起作用。有没有办法获得这种语法呢?

如果没有这个,只需要有两个参数列表就可以了:

val result = where (f1(1) * f2(2)) {
  def f1(x : Int) = x + 1
  def f2(x : Int) = x + 2
}

会很好,但这似乎很难。可以用两个参数列表调用一个宏吗?

2 个答案:

答案 0 :(得分:2)

对于第一个选项:我认为你可以将隐式转换本身设为无类型宏,不是吗?

对于第二个选项:您可以使用多个参数列表调用宏,是。呼叫站点上的多个列表将转换为定义站点上的多个列表,例如:

def myMacro(a: _)(b: _) = macro myMacro_impl

def myMacro_impl(c: Context)(a: c.Tree)(b: c.Tree): c.Tree = { ... }

将被称为:

myMacro(...)(...)

答案 1 :(得分:1)

答案:截至2013-03-08,无法在中缀位置使用无类型宏。引自Eugene Burmako的scala-user mailing list

  

目前,左边的参数必须首先进行类比检查   任何隐含的解决方案都可以解决。你可以写“class”   foo(x:_)“是一个疏忽 - 下划线语法应该是   仅适用于无类型的宏。

作为参考,我能够做到的最接近的是:

implicit class HasWhere(val exp : _) {
 def where(block : Unit) = macro whereInfix
}

def whereInfix(c : Context)(block : c.Expr[Unit]) = {
  import c.universe._

  val exp = Select(c.prefix.tree, TermName("exp"))
  val Expr(Block((inner, _))) = block
  val newinner = inner :+ exp
  Block(newinner : _*)
}