2015-10-11 107 views
2

我建立使用阶将筛选基于在DSL状态数据的DSL通过拉姆达参数的名称。查找斯卡拉

功能过滤器:

def filter(f: (Int) => (Int)) { 
// find what is the name (age) of lambda passed 
// query db with column name age and apply function f and return value 

} 

使用DSL作为:

filter( (age) => age > 10) 

我不能找到一种方法,要知道,在DSL age时,有没有办法?

暂时,我传递的字符串作为第一个参数如下图所示:

filter("age", (age) => age > 10) 

和改变过滤器采取的第一个参数为列名。

我想简化DSL。

+0

你可以添加'filter'函数的实际实现吗? –

+0

这将需要一个宏(如果有可能,我不知道)。 –

+1

如果你只是把它称为'filter(“age”,(_> 10))'',那么它不会简单吗? –

回答

3

目前可以得到的λ实例的参数的名称的唯一方法是通过声明Scala的宏,而不是Scala的方法为filter。宏将接收lambda的抽象语法树而不是lambda本身,所以它将能够分析lambda的参数的名称。

这里是如何做到这一点一个很小的例子:

import scala.language.experimental.macros 
import scala.reflect.macros.whitebox.Context 

object MyFilter { 
    def filter(p: Int => Int): Unit = macro filterImpl 
    def filterImpl(c: Context)(p: c.Expr[Int => Int]): c.Expr[Unit] = { 
    import c.universe._ 

    val Function(args, body) = p.tree 
    val ValDef(mods, name, tp, rhs) = args(0) 
    println(name) 

    reify { 
    () 
    } 
    } 
} 

上面,我们首先导入相关的包启用宏。然后,我们定义其实现filterImpl沿着高清宏filter。最后,我们实行宏观 - 我们模式的说法树比赛拖入Function树,然后在第一个参数(args(0)),最后格局的第一个参数匹配为ValDef树能够提取的名称。

你可以阅读更多关于宏here

+0

谢谢axel22。我会试试这个。看起来像完美的解决方案。任何已知的问题,如表现等。我相信宏也是实验性的。 – user5432812

+0

这是真的 - 宏仍然是实验性的。性能应该没有问题,因为宏体在编译期间执行。主要的缺点是你必须在两个模块(例如sbt项目)上重构你的代码 - 一个定义宏,另一个使用它,因为宏不能从定义它们的同一个编译运行中调用。 – axel22