2015-10-11 219 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