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