为了回应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
}
会很好,但这似乎很难。可以用两个参数列表调用一个宏吗?
答案 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 : _*)
}