论面向组合子程序设计方法 之 南无阿弥陀佛
生活随笔
收集整理的這篇文章主要介紹了
论面向组合子程序设计方法 之 南无阿弥陀佛
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
其實(shí),前面我還忘了提一個(gè)非常重要的基本組合子:singleton。?
這里補(bǔ)充提一下:?
Java代碼??class?SingletonComponent?implements?Component{?? ??private?final?Component?c;?? ??private?Object?val;?? ??public?Class?getType();{?? ????return?c.getType();;?? ??}?? ??public?synchronized?Object?create(Dependency?dep);{?? ????if(val!=null);?return?val;?? ????val?=?c.create(dep);;?? ????return?val;?? ??}?? ??public?synchronized?Class?verify(Dependency?dep);{?? ????if(val!=null);?return?val.getClass();;?? ????else?return?c.verify(dep);;?? ??}?? }???
代碼沒(méi)什么可說(shuō)的,就是最簡(jiǎn)單的singleton模式。?
用這個(gè)組合子,我們可以對(duì)任意的Component做singleton。?
下面接著說(shuō)monad。?
有了bind,很多的功能都可以自然推演出來(lái)了。?
比如我們前面用來(lái)刁難pico的那個(gè)例子,甚至,為了更強(qiáng)調(diào)復(fù)雜性,我們可以給B和A再另外增加一些參數(shù),這些參數(shù)要求從容器解析(畢竟,我們之所以需要容器,就是為了自動(dòng)解析一些依賴(lài)關(guān)系,要是全部依賴(lài)關(guān)系都hard-code,意義就不大了):?
Java代碼??void?A?createA();{?? ??B?b?=?new?B(...);;?? ??return?new?A(b,b,?...);;?? }??
用bind,我們的思路可以是這樣:?
1。用B的構(gòu)造函數(shù)生成一個(gè)Component。?
2。這個(gè)Component生成一個(gè)對(duì)象,?
3。這個(gè)產(chǎn)生的對(duì)象被傳遞給一個(gè)對(duì)應(yīng)A的Component當(dāng)作參數(shù)。這一步可以用bind來(lái)搞定。?
Java代碼??Component?b_component?=?Components.ctor(B.class);;?? return?new?BoundComponent(b_component,?new?Binder();{?? ??public?Component?bind(Object?b);{?? ????final?Component?arg?=?Components.value(b);;?? ????return?new?WithArgument(?? ??????new?WithArgument(a,?0,?arg);,?? ????1,?arg);;?? ??}?? });;??
Components.value(Object)是我們寫(xiě)的一個(gè)對(duì)ValueComponent的封裝靜態(tài)函數(shù)。?
為了避免總寫(xiě)冗長(zhǎng)的new SomeComponent(...),我們把一些常用的基本Component都寫(xiě)成名字較短的靜態(tài)函數(shù),放在Components類(lèi)里面。?
這樣,我們可以寫(xiě)Components.value(obj),而不是new ValueComponent(obj)。?
要是覺(jué)得敲鍵盤(pán)還是麻煩,你甚至可以創(chuàng)建一個(gè)Components對(duì)象cc。然后到處用這個(gè)對(duì)象:?
cc.value(obj)。舒服些了吧??
從上面的例子,我們可以看到,那個(gè)直接創(chuàng)建對(duì)象的createA函數(shù)中的兩個(gè)步驟,在我們高階的Component中也被分為兩部。?
而在兩個(gè)步驟之間的信息傳遞(那個(gè)b變量,從第一個(gè)步驟取得,然后在第二個(gè)步驟使用),則被用bind操作實(shí)現(xiàn)了。?
到這,也許我們?cè)撋焐鞈醒?。舒服地往椅子背上一?#xff0c;說(shuō):“啊。終于干完了!我可以用高階邏輯來(lái)模擬任何直接硬編碼創(chuàng)建對(duì)象的邏輯了”。?
這話(huà)倒也沒(méi)錯(cuò),有了bind,我們不再被局限于“構(gòu)造函數(shù)注射”,“setter注射”,“靜態(tài)工廠注射”等寥寥幾個(gè)注射方式;我們甚至可以對(duì)所謂的ioc type嗤之以鼻:“什么type1, type2?不過(guò)是我們可以處理的無(wú)數(shù)種情況中的幾種特例而已!”。?
我們可以處理if-else,可以處理循環(huán),遞歸,任何可以直接用java寫(xiě)出來(lái)的對(duì)象創(chuàng)建方式,我們都可以在高階邏輯上得到對(duì)應(yīng)的組合版本,只要我們有足夠的原子組合子。(所謂原字組合子,不過(guò)是:FunctionComponent, BeanComponent,ValueComponent幾種)?
比如,對(duì)應(yīng)于:?
Java代碼??X?createX();{?? ??A?a?=?A.instance(...);;?? ??if(a.isX(...););{?? ????return?new?X(...);;?? ??}?? ??else{?? ????return?new?Y(a,?...);.getX(...);;?? ??}?? }??
這里,所有的省略號(hào)都代表可能需要從容器解析的參數(shù)。使用高階Component對(duì)象而不是直接調(diào)用createX()函數(shù)的一個(gè)原因,就是我們想要把依賴(lài)解析隱藏起來(lái)并且集中靈活地配置和管理。?
對(duì)此,我們可以寫(xiě)成:?
Java代碼??Component?a_component?=?Components.static_method(A.class,?"instance");;?? return?new?BoundComponent(a_component,?new?Binder();{?? ??public?Component?bind(final?Object?a);{?? ????final?Component?isx_component?=?Components.method(a,?"isX");;?? ????return?new?BoundComponent(isx_component,?new?Binder();{?? ??????public?Component?bind(Object?isx);{?? ????????final?Boolean?v?=?(Boolean);isx;?? ????????if(v.booleanValue(););{?? ??????????return?Components.ctor(X.class);;?? ????????}?? ????????else{?? ??????????final?Coponent?y_component?=??? ???????????new?WithArgument(Components.ctor(Y.class);,?0,??? ??????????????Components.value(a););;?? ??????????return?new?BoundComponent(y_component,?new?Binder();{?? ????????????public?Component?bind(Object?y);{?? ??????????????return?Components.method(y,?"getX");;?? ????????????}?? ??????????});;?? ???????????? ????????}?? ??????}?? ????});;?? ??}?? });;??
稍微有點(diǎn)繞,如果你到此有點(diǎn)糊涂的話(huà),請(qǐng)重溫一下前面的簡(jiǎn)單的bind的例子,只要體會(huì)了bind的具體意義,上面的代碼不過(guò)是幾層bind的嵌套。?
好,如果你理解了bind,那么應(yīng)該能夠看懂上面的這段代碼了。它其實(shí)就是那個(gè)createX函數(shù)的嚴(yán)格翻譯。?
功能確實(shí)很強(qiáng)大了,就是這代碼寫(xiě)起來(lái)這個(gè) 煩 啊!對(duì)比一下createX和這個(gè)高階版本吧。我發(fā)現(xiàn)如果我多看幾眼這個(gè)所謂的"co"的代碼,我簡(jiǎn)直都要吐!如果說(shuō)createX這個(gè)函數(shù)的代碼是正常人說(shuō)話(huà),那么這個(gè)高階代碼就是唐僧念經(jīng):“南無(wú)阿彌陀佛,南無(wú)阿彌陀佛,南無(wú)阿彌陀佛...”,天啊!?
如果我們真要Combinator-oriented起來(lái),難道要整天寫(xiě)這種蹩腳代碼?是不是我們吐啊吐的就會(huì)習(xí)慣了呢??
pico的各個(gè)ComponentAdapter其實(shí)倒也就是這么寫(xiě),可是pico沒(méi)有bind,你很少需要寫(xiě)這么深的嵌套,甚至很少需要寫(xiě)匿名類(lèi)。?
如果我們把我們的組件系統(tǒng)比喻作pascal語(yǔ)言的話(huà),pico的那些decorator充其量不過(guò)是一個(gè)dos的批處理,不,遠(yuǎn)不如批處理靈活,應(yīng)該也就是一個(gè)簡(jiǎn)單的用戶(hù)界面上的幾個(gè)按鈕。?
那么有沒(méi)有什么辦法來(lái)簡(jiǎn)化語(yǔ)法呢??
倒是有一個(gè)想法:?
1。把Component從接口變成一個(gè)抽象類(lèi)。然后把一些常用的二元組合,比如bind,比如withArgument,withProperty,比如method,ifelse,都放在這個(gè)抽象類(lèi)里面。這樣,?
我們就可以避免寫(xiě):?
new SingletonComponent(c),而寫(xiě)c.singleton()。?
我們就可以避免寫(xiě):?
new BoundComponent(c1, ...),而寫(xiě):c1.bind(...)。?
可以避免寫(xiě):?
new WithArgument(c, 0, arg),而寫(xiě):c.withArgument(0, arg)。?
可以避免寫(xiě):?
Java代碼??new?BoundComponent(c1,?new?Binder();{?? ??public?Component?bind(Object?obj);{?? ????return?Components.method(obj,?"method");;?? ??}?? });;??
而寫(xiě)成:?
Java代碼??c1.method("method");;??
可以避免寫(xiě):?
Java代碼??new?BoundComponent(c1,?new?Binder();{?? ??public?Component?bind(Object?obj);{?? ????if(((Boolean);obj);.booleanValue(););{?? ??????return?a;?? ????}?? ????else?return?b;?? ??}?? });;??
而寫(xiě)成:?
Java代碼??c1.ifelse(a,b);;??
等等等等。?
這樣做,從架構(gòu)上確實(shí)有點(diǎn)損害,我們犧牲了“圍繞接口”的原則,而改為圍繞抽象類(lèi)了。?
但是,從實(shí)際效果考慮,我發(fā)現(xiàn)它損失的架構(gòu)上的美感,遠(yuǎn)遠(yuǎn)比不上它帶來(lái)的編碼上的方便程度。誰(shuí)讓我們用的是java呢,世上沒(méi)有十全十美的事情,就湊合吧。?
經(jīng)過(guò)這個(gè)改動(dòng),上面的對(duì)應(yīng)createX的高階代碼變成:?
Java代碼??Component?a_component?=?Components.static_method(A.class,?"instance");;?? return?a_component.bind(new?Binder();{?? ??public?Component?bind(final?Object?a);{?? ????final?Component?isx_component?=?Components.method(a,?"isX");;?? ????return?isx_component.ifelse(?? ??????Components.ctor(X.class);,?? ??????Components.ctor(Y.class);?? ????????.withArgument(0,?Components.value(a););?? ????????.method("getX");?? ????);;?? ??}?? });;??
稍微好些了。而如果我們不需要給Y的構(gòu)造函數(shù)指定參數(shù),那么效果還會(huì)更好。?
比如對(duì)?
Java代碼??X?createX();{?? ??A?a?=?A.instance(...);;?? ??if(a.isX(...););{?? ????return?new?X(...);;?? ??}?? ??else{?? ????return?new?Y(...);.getX(...);;?? ??}?? }??
高階代碼會(huì)變成:?
Java代碼??Component?a_component?=?Components.static_method(A.class,?"instance");;?? return?a_component.method("isX");.ifelse(?? ????Components.ctor(X.class);,?? ????Components.ctor(Y.class);?? ??????.withArgument(0,?Components.value(a););?? ??????.method("getX");?? );;??
又簡(jiǎn)潔了不少。?
當(dāng)然,說(shuō)實(shí)話(huà),如果我們把情況任意復(fù)雜化,比如:?
Java代碼??Y?createY();{?? ??a?=?A.createA(...);;?? ??b?=?B.createB(a,?...);;?? ??c?=?C.createC(a,b,...);;?? ??return?Y.create(a,b,c,...);;?? }??
要對(duì)createY寫(xiě)出高階對(duì)應(yīng)版本,這bind要嵌套三層,代碼無(wú)論如何不可能好看了。對(duì)此,我們只能聳聳肩說(shuō):無(wú)能為力了。因?yàn)槲覀冞@里已經(jīng)接觸到了java語(yǔ)言的底線。?
值得欣慰的是,至少:?
1。對(duì)簡(jiǎn)單需求,比如pico能夠處理的那些,我們的語(yǔ)法并不比pico麻煩。?
2。對(duì)復(fù)雜需求,pico不能處理,而只能通過(guò)自己實(shí)現(xiàn)ComponentAdapter實(shí)現(xiàn);而我們的co構(gòu)建出來(lái)的系統(tǒng),在沒(méi)有剝奪你自己實(shí)現(xiàn)Component的前提下,也提供了采用聲明式的語(yǔ)法來(lái)組合的方式。至于是選擇用熟悉的java語(yǔ)法來(lái)過(guò)程式地自己處理依賴(lài),還是用聲明式的高階邏輯來(lái)仍然讓系統(tǒng)處理依賴(lài),則是程序員的自由了。?
我們推薦,除非對(duì)非常復(fù)雜的需求,還是用聲明式的組合來(lái)處理更好。?
寫(xiě)到這里,不得不嘮叨一些語(yǔ)言了。就象是你也可以在c這個(gè)過(guò)程語(yǔ)言里面使用一些oo的技巧一樣,我們?cè)趈ava這個(gè)oo語(yǔ)言里面是可以使用一些co的技巧的。?
只不過(guò),缺乏語(yǔ)言上的良好支持,讓我們?cè)诓捎胏o設(shè)計(jì)的時(shí)候的代價(jià)有所增大。如何權(quán)衡?是co帶來(lái)的缺點(diǎn)(不方便調(diào)試,運(yùn)行效率低,語(yǔ)法麻煩)大,還是它帶來(lái)的好處(靈活應(yīng)對(duì)變化,減少代碼數(shù)量,方便重用)大,則是一個(gè)需要主觀經(jīng)驗(yàn)決定的事情了。?
其實(shí),在一個(gè)真正支持monad組合子的語(yǔ)言里面,createY會(huì)被類(lèi)似寫(xiě)成這樣:?
Java代碼??do?? ??a?<-?static_method(A.class,?"createA");;?? ??b?<-?static_method(B.class,?"createB");?? ????.withArgument(0,?a);;?? ??c?<-?static_method(C.class,?"createC");?? ????.withArgument(0,?a);.withArgument(1,?b);;?? ??return?(static_method(Y.class,?"create");?? ????.withArgument(0,a);.withArgument(1,b);.withArgument(2,c);;?? ??);??
所有的Binder匿名類(lèi)會(huì)被自動(dòng)生成。?
這叫"do-notation",是haskell里面用來(lái)方便處理monad組合子的利器。?
在我開(kāi)發(fā)的jaskell語(yǔ)言里面,對(duì)do-notation有類(lèi)似的支持。?
題外話(huà):?
最近,看到老莊設(shè)計(jì)的DJ里面說(shuō)要支持co。我覺(jué)得,如果僅僅象java這樣的所謂“支持”,那就和用C的函數(shù)指針號(hào)稱(chēng)支持OO一樣無(wú)趣了。?
一個(gè)可以說(shuō)得上對(duì)co有支持的語(yǔ)言,即使不直接支持do-notation,也應(yīng)該把寫(xiě)匿名類(lèi)的代價(jià)降到和一個(gè)lamda函數(shù)相接近的程度。?
即使我不能寫(xiě)?
Java代碼??a?<-?createA?? b?<-?createB?a??
也要能夠?qū)懗?#xff1a;?
Java代碼??createA?>>=?\a->createB?a??
這里補(bǔ)充提一下:?
Java代碼??
代碼沒(méi)什么可說(shuō)的,就是最簡(jiǎn)單的singleton模式。?
用這個(gè)組合子,我們可以對(duì)任意的Component做singleton。?
下面接著說(shuō)monad。?
有了bind,很多的功能都可以自然推演出來(lái)了。?
比如我們前面用來(lái)刁難pico的那個(gè)例子,甚至,為了更強(qiáng)調(diào)復(fù)雜性,我們可以給B和A再另外增加一些參數(shù),這些參數(shù)要求從容器解析(畢竟,我們之所以需要容器,就是為了自動(dòng)解析一些依賴(lài)關(guān)系,要是全部依賴(lài)關(guān)系都hard-code,意義就不大了):?
Java代碼??
用bind,我們的思路可以是這樣:?
1。用B的構(gòu)造函數(shù)生成一個(gè)Component。?
2。這個(gè)Component生成一個(gè)對(duì)象,?
3。這個(gè)產(chǎn)生的對(duì)象被傳遞給一個(gè)對(duì)應(yīng)A的Component當(dāng)作參數(shù)。這一步可以用bind來(lái)搞定。?
Java代碼??
Components.value(Object)是我們寫(xiě)的一個(gè)對(duì)ValueComponent的封裝靜態(tài)函數(shù)。?
為了避免總寫(xiě)冗長(zhǎng)的new SomeComponent(...),我們把一些常用的基本Component都寫(xiě)成名字較短的靜態(tài)函數(shù),放在Components類(lèi)里面。?
這樣,我們可以寫(xiě)Components.value(obj),而不是new ValueComponent(obj)。?
要是覺(jué)得敲鍵盤(pán)還是麻煩,你甚至可以創(chuàng)建一個(gè)Components對(duì)象cc。然后到處用這個(gè)對(duì)象:?
cc.value(obj)。舒服些了吧??
從上面的例子,我們可以看到,那個(gè)直接創(chuàng)建對(duì)象的createA函數(shù)中的兩個(gè)步驟,在我們高階的Component中也被分為兩部。?
而在兩個(gè)步驟之間的信息傳遞(那個(gè)b變量,從第一個(gè)步驟取得,然后在第二個(gè)步驟使用),則被用bind操作實(shí)現(xiàn)了。?
到這,也許我們?cè)撋焐鞈醒?。舒服地往椅子背上一?#xff0c;說(shuō):“啊。終于干完了!我可以用高階邏輯來(lái)模擬任何直接硬編碼創(chuàng)建對(duì)象的邏輯了”。?
這話(huà)倒也沒(méi)錯(cuò),有了bind,我們不再被局限于“構(gòu)造函數(shù)注射”,“setter注射”,“靜態(tài)工廠注射”等寥寥幾個(gè)注射方式;我們甚至可以對(duì)所謂的ioc type嗤之以鼻:“什么type1, type2?不過(guò)是我們可以處理的無(wú)數(shù)種情況中的幾種特例而已!”。?
我們可以處理if-else,可以處理循環(huán),遞歸,任何可以直接用java寫(xiě)出來(lái)的對(duì)象創(chuàng)建方式,我們都可以在高階邏輯上得到對(duì)應(yīng)的組合版本,只要我們有足夠的原子組合子。(所謂原字組合子,不過(guò)是:FunctionComponent, BeanComponent,ValueComponent幾種)?
比如,對(duì)應(yīng)于:?
Java代碼??
這里,所有的省略號(hào)都代表可能需要從容器解析的參數(shù)。使用高階Component對(duì)象而不是直接調(diào)用createX()函數(shù)的一個(gè)原因,就是我們想要把依賴(lài)解析隱藏起來(lái)并且集中靈活地配置和管理。?
對(duì)此,我們可以寫(xiě)成:?
Java代碼??
稍微有點(diǎn)繞,如果你到此有點(diǎn)糊涂的話(huà),請(qǐng)重溫一下前面的簡(jiǎn)單的bind的例子,只要體會(huì)了bind的具體意義,上面的代碼不過(guò)是幾層bind的嵌套。?
好,如果你理解了bind,那么應(yīng)該能夠看懂上面的這段代碼了。它其實(shí)就是那個(gè)createX函數(shù)的嚴(yán)格翻譯。?
功能確實(shí)很強(qiáng)大了,就是這代碼寫(xiě)起來(lái)這個(gè) 煩 啊!對(duì)比一下createX和這個(gè)高階版本吧。我發(fā)現(xiàn)如果我多看幾眼這個(gè)所謂的"co"的代碼,我簡(jiǎn)直都要吐!如果說(shuō)createX這個(gè)函數(shù)的代碼是正常人說(shuō)話(huà),那么這個(gè)高階代碼就是唐僧念經(jīng):“南無(wú)阿彌陀佛,南無(wú)阿彌陀佛,南無(wú)阿彌陀佛...”,天啊!?
如果我們真要Combinator-oriented起來(lái),難道要整天寫(xiě)這種蹩腳代碼?是不是我們吐啊吐的就會(huì)習(xí)慣了呢??
pico的各個(gè)ComponentAdapter其實(shí)倒也就是這么寫(xiě),可是pico沒(méi)有bind,你很少需要寫(xiě)這么深的嵌套,甚至很少需要寫(xiě)匿名類(lèi)。?
如果我們把我們的組件系統(tǒng)比喻作pascal語(yǔ)言的話(huà),pico的那些decorator充其量不過(guò)是一個(gè)dos的批處理,不,遠(yuǎn)不如批處理靈活,應(yīng)該也就是一個(gè)簡(jiǎn)單的用戶(hù)界面上的幾個(gè)按鈕。?
那么有沒(méi)有什么辦法來(lái)簡(jiǎn)化語(yǔ)法呢??
倒是有一個(gè)想法:?
1。把Component從接口變成一個(gè)抽象類(lèi)。然后把一些常用的二元組合,比如bind,比如withArgument,withProperty,比如method,ifelse,都放在這個(gè)抽象類(lèi)里面。這樣,?
我們就可以避免寫(xiě):?
new SingletonComponent(c),而寫(xiě)c.singleton()。?
我們就可以避免寫(xiě):?
new BoundComponent(c1, ...),而寫(xiě):c1.bind(...)。?
可以避免寫(xiě):?
new WithArgument(c, 0, arg),而寫(xiě):c.withArgument(0, arg)。?
可以避免寫(xiě):?
Java代碼??
而寫(xiě)成:?
Java代碼??
可以避免寫(xiě):?
Java代碼??
而寫(xiě)成:?
Java代碼??
等等等等。?
這樣做,從架構(gòu)上確實(shí)有點(diǎn)損害,我們犧牲了“圍繞接口”的原則,而改為圍繞抽象類(lèi)了。?
但是,從實(shí)際效果考慮,我發(fā)現(xiàn)它損失的架構(gòu)上的美感,遠(yuǎn)遠(yuǎn)比不上它帶來(lái)的編碼上的方便程度。誰(shuí)讓我們用的是java呢,世上沒(méi)有十全十美的事情,就湊合吧。?
經(jīng)過(guò)這個(gè)改動(dòng),上面的對(duì)應(yīng)createX的高階代碼變成:?
Java代碼??
稍微好些了。而如果我們不需要給Y的構(gòu)造函數(shù)指定參數(shù),那么效果還會(huì)更好。?
比如對(duì)?
Java代碼??
高階代碼會(huì)變成:?
Java代碼??
又簡(jiǎn)潔了不少。?
當(dāng)然,說(shuō)實(shí)話(huà),如果我們把情況任意復(fù)雜化,比如:?
Java代碼??
要對(duì)createY寫(xiě)出高階對(duì)應(yīng)版本,這bind要嵌套三層,代碼無(wú)論如何不可能好看了。對(duì)此,我們只能聳聳肩說(shuō):無(wú)能為力了。因?yàn)槲覀冞@里已經(jīng)接觸到了java語(yǔ)言的底線。?
值得欣慰的是,至少:?
1。對(duì)簡(jiǎn)單需求,比如pico能夠處理的那些,我們的語(yǔ)法并不比pico麻煩。?
2。對(duì)復(fù)雜需求,pico不能處理,而只能通過(guò)自己實(shí)現(xiàn)ComponentAdapter實(shí)現(xiàn);而我們的co構(gòu)建出來(lái)的系統(tǒng),在沒(méi)有剝奪你自己實(shí)現(xiàn)Component的前提下,也提供了采用聲明式的語(yǔ)法來(lái)組合的方式。至于是選擇用熟悉的java語(yǔ)法來(lái)過(guò)程式地自己處理依賴(lài),還是用聲明式的高階邏輯來(lái)仍然讓系統(tǒng)處理依賴(lài),則是程序員的自由了。?
我們推薦,除非對(duì)非常復(fù)雜的需求,還是用聲明式的組合來(lái)處理更好。?
寫(xiě)到這里,不得不嘮叨一些語(yǔ)言了。就象是你也可以在c這個(gè)過(guò)程語(yǔ)言里面使用一些oo的技巧一樣,我們?cè)趈ava這個(gè)oo語(yǔ)言里面是可以使用一些co的技巧的。?
只不過(guò),缺乏語(yǔ)言上的良好支持,讓我們?cè)诓捎胏o設(shè)計(jì)的時(shí)候的代價(jià)有所增大。如何權(quán)衡?是co帶來(lái)的缺點(diǎn)(不方便調(diào)試,運(yùn)行效率低,語(yǔ)法麻煩)大,還是它帶來(lái)的好處(靈活應(yīng)對(duì)變化,減少代碼數(shù)量,方便重用)大,則是一個(gè)需要主觀經(jīng)驗(yàn)決定的事情了。?
其實(shí),在一個(gè)真正支持monad組合子的語(yǔ)言里面,createY會(huì)被類(lèi)似寫(xiě)成這樣:?
Java代碼??
所有的Binder匿名類(lèi)會(huì)被自動(dòng)生成。?
這叫"do-notation",是haskell里面用來(lái)方便處理monad組合子的利器。?
在我開(kāi)發(fā)的jaskell語(yǔ)言里面,對(duì)do-notation有類(lèi)似的支持。?
題外話(huà):?
最近,看到老莊設(shè)計(jì)的DJ里面說(shuō)要支持co。我覺(jué)得,如果僅僅象java這樣的所謂“支持”,那就和用C的函數(shù)指針號(hào)稱(chēng)支持OO一樣無(wú)趣了。?
一個(gè)可以說(shuō)得上對(duì)co有支持的語(yǔ)言,即使不直接支持do-notation,也應(yīng)該把寫(xiě)匿名類(lèi)的代價(jià)降到和一個(gè)lamda函數(shù)相接近的程度。?
即使我不能寫(xiě)?
Java代碼??
也要能夠?qū)懗?#xff1a;?
Java代碼??
組合并不僅僅是幾個(gè)簡(jiǎn)單的decorator套起來(lái)。真正復(fù)雜的co里,不同組合子之間是需要通過(guò)bind來(lái)通信的。而組合子之間的通信能力才是co強(qiáng)大的根源。
from:?http://ajoo.iteye.com/blog/23326
總結(jié)
以上是生活随笔為你收集整理的论面向组合子程序设计方法 之 南无阿弥陀佛的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 论面向组合子程序设计方法 之 重构
- 下一篇: 论面向组合子程序设计方法 之 重构2