2011-07-21 56 views
4

我試圖創建一個DSL並遇到問題。我有這些定義:斯卡拉 - 省略應用DSL的方法的括號

case class Var(name: String) 
case class Lam(v: Var, t: Var) 
val (a, b) = (Var("a"), Var("b")) 

我希望能夠做到這一點:

scala> \ a b 
Lam(Var(a),Var(b)) 

在括號落下的規則讀了起來,我看到我需要的是把每一個參數鏈功能,所以我創建了一系列執行建設「建設者」類:

class LamBuilderB(v: Var) { 
    def apply(t: Var) = Lam(v, t) 
} 

class LamBuilderA { 
    def apply(v: Var) = new LamBuilderB(v) 
} 

val \ = new LamBuilderA 

我希望這會工作,因爲每個apply只有一個參數。但是,它似乎並不像下探括號是合法的,因爲apply它要處理的參數作爲方法名稱:

scala> \(a)(b) 
res95: Lam = Lam(Var(a),Var(b)) 

scala> \ a b 
error: value a is not a member of LamBuilderA 
    \ a b 
    ^

任何想法如何我怎樣才能不帶括號的DSL語法?

獎金問題:我能得到這個?:

scala> \a.b 
Lam(Var(a),Var(b)) 
+1

我當然_hope_你不能得到'\ ab'!重載'''不是我所說的嵌入式DSL的好主意。 –

回答

6

你可以八九不離十使用4的一個一元前綴運算符(~!+-):

trait Expr { 
    def &(other: Expr) = Lam(this, other) 
    def unary_~ = this 
} 

case class Var(name: String) extends Expr 
case class Lam(a: Expr, b: Expr) extends Expr 

scala> ~ Var("a") & Var("b") 
res0: Lam = Lam(Var(a),Var(b)) 

scala> ~ Var("a") & Var("b") & Var("c") 
res1: Lam = Lam(Lam(Var(a),Var(b)),Var(c)) 
+0

感謝這個有趣的答案。我認爲我將不得不堅持'\(a,b)'作爲我的語法,但利用一元運算符是一個好主意。 – dhg