2014-01-07 65 views
0

我試圖用Dart在應用程序中簡潔地定義實體,遵循代碼=配置的習慣用法。由於我將定義許多實體,因此我希望儘可能使代碼儘量簡潔和易讀。使用Dart作爲DSL

在努力保持樣板接近0線有可能,我最近寫了一些像這樣的代碼:

// man.dart 
part of entity_component_framework; 

var _man = entity('man', (entityBuilder) { 
    entityBuilder.add([TopHat, CrookedTeeth]); 
}) 

// test.dart 
part of entity_component_framework; 
var man = EntityBuilder.entities['man']; // null, since _man wasn't ever accessed. 

entity方法相關聯的entityBuilder傳遞到函數的名稱(「男人」在這種情況下)。 var _man存在,因爲只有變量分配才能在Dart中處於頂層。這似乎是將Dart用作DSL的最簡潔的方式。

雖然我不指望的一件事是懶惰的初始化。如果我從來沒有訪問過_man--而且我也不打算這樣做,因爲entity函數整齊地存儲了我在另一個數據結構中需要的所有相關信息 - 那麼entity函數永遠不會運行。 This is a feature, not a bug

那麼,在給定延遲初始化限制的情況下,使用Dart作爲DSL的最簡單方法是什麼?

+1

我認爲你需要提供更多的上下文。我不清楚你想要做什麼。但在小圖中,你可以使它成爲(entityBuilder)=> entityBuilder.add([TopHat,CrookedTeeth]);並有add方法返回已添加的東西。然後你可以說var man = _man; –

+0

我編輯了這個問題。基本上,我試圖使用Dart配置實體,而不是解析YAML或其他配置文件。但是,懶惰初始化阻止我使用更簡潔的樣式。 – ALW

+0

https://gist.github.com/radicaled/8309609 - 以另一種方式說話,懶惰的初始化阻止我在不首先接觸臨時變量的情況下使用DSL(我不需要使用它,因爲我會在示例中直接使用數據存儲「potatoSack」)。 – ALW

回答

4

因此,正如您所指出的那樣,這是Dart在告知之前不會運行任何代碼的功能。所以如果你想要發生什麼,你需要在運行的代碼中完成。一些可能性

將你的調用放到main()函數中的entity()中。我假設你不想這樣做,並且可能希望人們能夠在不修改原稿的情況下將更多這些文件添加到其他文件中。

如果您願意承擔鏡像的開銷(如果它們僅限於此庫,可能沒有那麼多),請使用它們來查找該庫中的所有頂級變量並訪問它們。或者將它們定義爲函數或getter。但我認爲你喜歡這個變量是自動一次性的屬性。你想要使用MirrorsUsed註解。

一個變化就是使用註釋來標記你想要初始化的東西。雖然這是類似的,你必須遍歷註釋的東西,我認爲這也需要鏡像。

+0

同意,鏡子是你最好的選擇。 如果我的理解正確,您想要聲明性地定義實體,以便它們在全局數據結構中定義。因爲你已經發現了:代碼不是隱式執行的,你需要明確地訪問一個getter或者調用一個方法,或者只是訪問一個懶惰的初始化字段。這意味着需要觸發初始化代碼。您需要在某處調用某個地方(也許讓EntityBuilder爲一個懶惰的初始化對象而不是類),並使用鏡像來查找聲明。 – lrn

+0

我使用'dart:mirrors'來解決符合特定命名方案的私有頂級變量聲明。 10個額外的代碼行,但沒有那麼糟糕,我想所有的事情都考慮在內。 – ALW