我問了自己這個問題幾次,並提出了一個解決方案,感覺很骯髒。也許你可以給我任何建議,因爲我認爲這是每個用Scala編寫的DSL的基本問題。斯卡拉DSL沒有額外的語法
我想擁有嵌套對象的層次結構,而無需添加任何額外的語法。規格是一個很好的例子:
MySpec extends Specification {
"system" should {
"example0" in { ... }
"example1" in { ... }
"example2" in { ... }
}
"system" can {
"example0" in { ... }
}
}
例如,我不必寫"example0" in { ... } :: "example1" in { ... } :: "example2" in { ... } :: Nil
。
這和我想要的行爲完全一樣。我認爲這是通過在規格的規範類像一個隱含的定義來實現(請不要如果你是規格作者和得罪我missunderstood東西:))現在
implicit def sus2spec(sus: Sus): Specification = {
suslist += sus
this
}
我主要的問題出現時,我想嵌套這些對象。想象一下,我有這樣的語法:
root: statement*;
statement:
IDENT '{' statement* '}'
| declaration*
;
declaration: IDENT ':=' INT+;
我想轉換爲DSL,看起來像這樣的:
MyRoot extends Root {
"statement0" is {
"nested_statement0" is {
"nested_nested_statement0" is {
"declaration0" := 0
}
"declaration1" := 1
"declaration2" := 2
}
"declaration3" := 3
}
"statement1" is {
"declaration4" := 4
}
}
即出現在這裏對我來說是隱式的解決方案不起作用的問題。隱式定義將在根對象的範圍內執行,這意味着我會將所有對象添加到根並且層次結構丟失。
然後我想我可以使用類似Stack [聲明]的東西。每次致電is
時,我都可以推送一個對象,但感覺非常髒。
用一句話來說明問題:如何創建一個遞歸的DSL,並尊重其層次結構而不添加任何額外的語法,並且是否有解決方案僅對不可變對象執行此操作?
請注意,您可以很好地在規格中嵌套示例:http://code.google.com/p/specs/wiki/DeclareSpecifications#Sub_examples因此解決方案應該在那裏。 – 2010-07-19 10:20:06
謝謝你指出。我想我已經找到了解決方案:「if(m.erasure == this.getClass)hasSomeSubExamples = true」。那麼也許我應該堅持我的可變堆棧。 – 2010-07-19 12:56:34