Posted on 2007-03-04 18:14
canonical 閱讀(1654)
評論(0) 編輯 收藏 所屬分類:
設計理論
?? 最近D語言發布了1.0版,這是一個由編譯器開發者所設計的編譯語言,語法類似C++, 但是針對C++的弊病作了大量修正,并增加了很多現代特征,其中還是有一些新意在其中的。http://www.digitalmars.com/d/overview.html 我對其比較感興趣的部分是D語言明確提出的編譯期運行的概念。雖然C++讓大眾了解了meta programming技術,很多人因此認為meta programming的威力在于類型演算,但是在我看來meta programming的真正作用在于在編譯期可以“動態”產生或調整代碼結構。它依賴于類型是因為我們只能利用類型來承載一些額外信息, 這無疑也是對于類型的一種濫用。在D語言中template所接受的不僅僅是類型, 或者類型的類型,它可以是任何符號.
? template MixInAttr(T, char[] name){?
???? mixin(" T _" ~ name ~";");
???? mixin(" T "~name~"(){ return _"~name~"; }");
???? mixin(" void "~name~"(T v){ _"~name~" = v;}");
? }?
?
? template MixInOtherAttr(T, T v){
??? T _otherAttr = v;
???
??? int otherAttr(){ return _otherAttr; }
? }
?
? const int myValue = 1;
?
? int addFunc(int x){
??? return x + 1;
? }
??
? class MyTest{?
???? mixin MixInAttr!(int, "myAttr");?
???? mixin MixInOtherAttr!(int,4);
????
???? static if(addFunc(myValue) 〉 0){
??????? int testFunc(){ return 5;}
???? }
? }
?
? void main(){?
???? auto t = new MyTest;
???? t.myAttr = 3;
???? int v = t.myAttr;???
???? v = t.otherAttr;
???? t.testFunc();
? }??
? 不過現在編譯期運行無疑是一個正在探索的方向, 在D語言中的使用方式并不是非常理想的, 在形式和功能實現上都存在著重大改進的可能.?
?
? 在witrix平臺的tpl模板語言中,我們也引入了編譯期運行的概念,只是tpl的語言特征非常簡單再加上xml格式特殊的規范性,編譯期運行在tpl中的實現是非常直接和明確的.在tpl中定義了<cp:run〉標簽,它的內容在編譯期運行, 輸出結果(xml字符串)將被繼續編譯. 在<cp:run〉中可以執行任何有效的tpl代碼, 它們在編譯期狀態空間中運行. 例如
?〈cp:run〉
?? 〈c:forEach var="_x" items="${tagBody.children()}"〉
?????? bla bla bla...
?? 〈/c:forEach〉
?〈/cp:run〉
在EL表達式中我們通過cp前綴實現普通調用和編譯期調用的混雜.
? 〈cp:const class="mypkg.MyConstantClass"/〉
? 〈c:eval expr="${myFunc(cp:const.MY_CONST, commonVar, cp:funcInCompileTime())}" /〉
? 〈cp:compile test="${exprInCompileTime}"〉
???? any tpl ...
? 〈/cp:compile〉
?其實當我們把改進的目光開始放到編譯期的結構方面的時候, 可以做的工作是非常多的. 例如從結構上看, 繼承策略相當是類結構的一種一階替換策略.
? 類B(methodB) extends 類A(methodA, methodB)? ==〉 類B(methodA[inA], methodB[inB])
如果我們放棄概念層面上的糾纏,而如同template那樣只關注語法結構, 則可以發展出更加復雜的替換操作.
? NODE_B(?????????????????????????? NODE_A(????????????????????????????????? NODE_B(
??? SUB_NODE_A1???????〉〉??? SUB_NODE_A1???????????? ==〉??? SUB_NODE_A1
????? SUB_NODE_B11????????????????? SUB_NODE_A11?????????????????????????? SUB_NODE_B11
???????????????????????????????????????????????????? SUB_NODE_A12??????????????????????????SUB_NODE_A12
? )????????????????????????????????????????? )?????????????????????????????????????????????????????? )
C++中及D語言中的template技術在某種意義上相當于是在代碼結構中預留了空洞, 可以實現跨越類結構的替換填充. 只是D語言挖洞的能力無疑比C++強大的多.?
? 如果我們考察的再細致一些, 就會發現兩個語法節點的融合也是存在多種策略的.
? B 〉〉 A ==〉 (remove_A, replace_A, insert_B_before_A, insert_B_after_A, insert_B_into_A, insert_A_into_B)
而通過insert_A_into_B/insert_B_into_A策略既可實現所謂的AOP intercept操作. http://canonical.javaeye.com/blog/34941?在witrix平臺的BizFlow技術中, 我們通過高級的結構融合策略實現為任意實體引入流程支持. 最簡單的情況下我們所需要做的工作只是增加一個語法元素
?〈bizflow extends="myflow"〉
引入流程意味著對界面的一系列修正, 例如增加,刪除某些菜單, 同時要增加很多流程相關函數, 對某些函數實施AOP操作, 在各處引入權限控制等等, 這些都可以通過extends操作引入.
? 在傳統上, 編譯器結構是固化的, 它所編譯的代碼結構是固化的, 而它所編譯出的代碼也是固化的, 但是現代語言的各種發展正致力于在各個層面引入動態性. 編譯期運行抑或是編譯期結構操縱技術的引入是在一個層面上打開了潘多拉魔盒. 它讓我們看到了前所未有的技術可能性, 但它無疑也是危險的,難以控制的. 我們目前的做法是盡量克制,只在局部使用, 但我相信它在很多語言中都是可以在理論上嚴格定義,并精確實現的, 我們最終也能夠找到合適的形式來約束它的破壞性. 在這個過程中我們需要引入更多的物理化的視角。