5

为了回答这个问题,我一直在尝试使用宏天堂分支在 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
}

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

4

2 回答 2

2

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

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

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

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

将被称为:

myMacro(...)(...)
于 2013-03-06T19:05:41.283 回答
1

答:从 2013-03-08 起,无法在中缀位置使用无类型宏。在scala-user 邮件列表中引用 Eugene Burmako :

目前,必须先对左侧的参数进行类型检查,然后才能启动任何隐式解析。您可以编写“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 : _*)
}
于 2013-03-08T13:53:29.963 回答