2008-10-29 68 views
22

什麼是最酷的有點實用元編程黑客你已經完成或看到在D編程語言完成?比較實用的方法是排除編譯時光線追蹤器等。D模板:最酷的破解

回答

8

在徹底最酷的方面,我有要說Kirk McDonald's PyD(以及其他類似的綁定),因爲它們在檢測和處理大量不同類型以及複雜代碼生成方面做了大量工作。

也就是說,PyD只贏了,因爲BLADE在技術上使用CTFE,而不是模板。

更爲個人的觀點,D模板在我的一個研究項目中得到了廣泛的應用。這是一個模擬框架,模塊可以定義他們自己的私有數據類型。向框架公開新的用戶類型需要一行代碼,該代碼爲該類型創建XML解析器以及相關的網絡序列化/反序列化代碼。

8

DParse在豬肉餅的工具是一個模板解析器生成。但是,ldc是唯一一個運行編譯時GC的D編譯器(但即使如此,它也有幾個奇怪的隨機崩潰)。我已經玩了一下,你可以做一些有趣的事情,如配置文件解析和東西,但直到編譯時GC完全運行,你不能做大事情。

+5

給它一個D大小的語法(~200個生產)「僅」需要7分鐘和700MB來編譯。 (完全披露,我寫了dparse) – BCS 2008-11-04 18:42:01

6

我最喜歡的是ElemType和關鍵字類型從tools.base:

template ElemType(T) { 
    alias typeof((function() { 
    foreach (elem; Init!(T)) return elem; assert(false); 
    })()) ElemType; 
} 

template KeyType(T) { 
    alias typeof((function() { 
    foreach (key, elem; Init!(T)) return key; assert(false); 
    })()) KeyType; 
} 
5

我會回答我自己的問題,因爲這個問題在我問到時不存在。我給垃圾收集器寫了一個補丁,它使用模板並編譯時間自省來爲任意複雜的用戶定義類型生成指針偏移量信息,以便進行精確的堆掃描,而不是在編譯器中完成。

4

我寫了一個memoize的()函數,它的標題是這樣的(代碼是有點長了粘貼在這裏):

汽車memoize的(TFunc)(TFunc FUNC);它的作用是給它一個函數的地址,它返回一個強類型委託(與原函數相同的簽名和返回類型),它緩存原函數的返回值,以便調用它兩次使用相同的參數只調用一次底層函數。例如,這是斐波那契數列的「遞歸」定義,它以線性而不是指數時間執行:

uint fib(uint n) {return n> 0? n> 1?(n - 1)+ memoize(& fib)(n - 2):1:0;記憶(& fib) }

您可以正常調用它,如:fib(1000);


編輯:我發佈的鏈接的前代碼相當可怕; this version is much more elegant

+1

將代碼發佈到github並分享它。那麼,如果你想。 – 2010-12-14 16:41:37

6

一個例子是D的標準庫中的bitfields工具,它生成從用戶指定的佈局開始的位字段操作代碼。

Tuple facility是另一個例子。它根據用戶提供的類型和可選名稱生成一個元組。除了注入已命名的字段外,沒有太多生成的umph,但我認爲這是一個說明性示例。

不知道蘭伯特的利用我只是說memoize的到標準庫 - 參見here的文檔,here的代碼,並here對相關新聞組討論。

我工作的另一個工具是一個高階函數,它將積分或實值函數列表(例如提供快速指數)。這還沒有準備好發佈。

一旦在編譯過程中允許創建對象,將很容易創建例如正則表達式引擎,在編譯過程中執行所有自動機生成。

2

混入閱讀並從Stream對象編寫簡單的結構:

template TStructReader() { 
     private alias typeof(*this) T; 
     static T opCall(Stream stream) { 
       assert(stream.readable); 
       T ret; stream.readExact(&ret, T.sizeof); 
       return ret; 
     } 
} 

template TStructWriter() { 
     private alias typeof(*this) T; 
     void write(Stream stream) { 
       assert(stream.writeable); 
       stream.writeExact(this, T.sizeof); 
     } 
} 

使用方法如下:

align (1) struct MyStruct { 
     ... definitions here ... 
     mixin TStructReader; 
     mixin TStructWriter; 
} 

auto ms = MyStruct(stream); 
ms.write(stream); 
2

LuaD也廣泛使用元編程與Lua的無縫交互。 您可以使用單個命令註冊整個班級。