FP不是一個(gè)什么全新的概念,在lisp等語(yǔ)言中被廣泛應(yīng)用,其設(shè)計(jì)方法向我們描繪了一個(gè)美好的世界,不過(guò)在OO的世界里應(yīng)用卻還是要費(fèi)一些力氣的。為了更好的應(yīng)用FP,需要學(xué)習(xí)一下現(xiàn)有的實(shí)踐。
?
一、回顧一下函數(shù)式編程的幾個(gè)特性:
1. 閉包計(jì)算和高階函數(shù)。
?? 函數(shù)本身是first class對(duì)象,閉包是起函數(shù)作用并可以像對(duì)象一樣操作的。
?? 高階函數(shù)是可以接受一個(gè)函數(shù)為參數(shù),并可以返回一個(gè)函數(shù)。?????
2. 延遲計(jì)算(lazy evaluation)
?? 不是在函數(shù)綁定時(shí)計(jì)算,而是在求值時(shí)計(jì)算。
3. 遞歸的計(jì)算機(jī)制????
4. 引用透明
??? 同樣的輸入返回同樣的結(jié)果,與上下文無(wú)關(guān)。????
5. 沒(méi)有副作用
??? 賦值后不能更改,既成為constant?????
?
二、OO世界中FP的身影。
The First:JDK下的FP?
1.??閉包計(jì)算的例子如:BigDecimal.add(…).add(…).multiply(…).substract(…)?
?????高階函數(shù)一個(gè)例子是:Collections和Comparator接口,Comparator的操作是個(gè)閉包操作, 而Collections的sort以它為參數(shù)。?
2.??沒(méi)有副作用的例子如下:?
?????BigDecimal.add(…).add(…).multiply(…).substract(…)?
?????String.subString(...)
?
The Second:DDD的Specification?
DDD一書提出了specification(chapter 10代碼就不貼了),不僅統(tǒng)一了Domain Model中不同的建模概念,而且應(yīng)用FP的閉包能力在specification讓人耳目一新。
?
The Third:CO編程?
CO編程的概念是ajoo在javaeye論壇上提出(http://forum.javaeye.com/viewtopic.php?t=15130)?。
在論戰(zhàn)中舉了logger和action兩個(gè)例子,都讓人看到了FP對(duì)系統(tǒng)開(kāi)發(fā)的過(guò)程和結(jié)構(gòu)巨大作用。?
??
BTW:buaawhl總結(jié)了functor的幾種組合情況(http://forum.javaeye.com/viewtopic.php?t=21533, 以下是簡(jiǎn)化版,略有修改)?
1. Functor組合 - Combinator, Pipe?
????Functor有多個(gè),參數(shù)只有一個(gè)。這一類的特點(diǎn)是,F(xiàn)unctor移動(dòng),參數(shù)不動(dòng)。?
2. 參數(shù)集合 - Visitor, Map, Filter, Reduce?
????這一類比較有趣。參數(shù)是多個(gè),是一個(gè)集合,F(xiàn)unctor可以是一個(gè)(也可能是多個(gè))。?
????這一類的特點(diǎn)是,F(xiàn)unctor不動(dòng),參數(shù)移動(dòng)。?
3. Functor組合,參數(shù)集合 - Curry, Factory Chain?
????最復(fù)雜的類型,就是這一類了。Functor移動(dòng),參數(shù)也移動(dòng)。?
????
關(guān)于Curry,是FP的另一個(gè)特性。?
舉個(gè)例子:F(x, y, z) = 2 * x + y - z。?
F(1, 2, 3) 用Curry的方式寫就是,f(1)(2)(3)。這是FP語(yǔ)法。?
由于FP下沒(méi)有成員變量,只好借用Curry + Closure來(lái)積累多個(gè)變量。?
換成類似于c, java, c#的語(yǔ)法來(lái)寫,就是Factory Chain的寫法。?
?????factory.generate(1).generate(2).generate(3);?
這里的關(guān)鍵是,上一個(gè)Functor處理參數(shù)的結(jié)果產(chǎn)生了下一個(gè)Functor,下一個(gè)Functor繼續(xù)處理下一個(gè)參數(shù),產(chǎn)生下一個(gè)Functor。?
如java世界中著名的orm框架hibernate的criteria和Query:SessionFactory.newSession(..).newQuery(…).setParameter(…).setParameter(…)?
等等形式,都具有Curry, Factory Chain的形式特點(diǎn)。雖然有時(shí)候,F(xiàn)unctor返回的是自己。
?
The Four and so on?
還不知道,但相信還有更多。
?
三、回顧小結(jié)應(yīng)用現(xiàn)狀:?
1. JDK和Hibernate的設(shè)計(jì)提高了開(kāi)發(fā)過(guò)程的體驗(yàn),還沒(méi)有對(duì)系統(tǒng)開(kāi)發(fā)有大的影響(或許我的認(rèn)識(shí)還太過(guò)于膚淺)?
2. 而DDD的例子,則實(shí)踐了FP的閉包。封裝了對(duì)返回值的操作能力,相當(dāng)于specification的and,or和not包裝了對(duì)操作符調(diào)用。?
??
BTW:DDD例子中,不同的函數(shù)組合后共同操作相同輸入?yún)?shù)。實(shí)踐中還會(huì)出現(xiàn)不同函數(shù)組合在一起,但各自有各自的輸入?yún)?shù)。對(duì)于可能存在的Pipe組合,使得操作值和返回值是同一類型,相當(dāng)于functor包裝了操作符。?
??
3. ajoo的CO例子實(shí)踐了FP的高階函數(shù)(實(shí)踐后看上去像Decorate模式,不過(guò)出發(fā)點(diǎn)不一樣)。?
封裝了對(duì)流程的控制的能力,提供sequenue和pipe等的計(jì)算能力。這樣的設(shè)計(jì)要求開(kāi)發(fā)者明確了解對(duì)高階函數(shù)和輸入函數(shù)的關(guān)系。另外CO沒(méi)有提供閉包能力。?
??
無(wú)論如何,現(xiàn)有的幾個(gè)實(shí)踐:JDK,hibernate,ajoo的例子和DDD的例子都說(shuō)明了:
基于不同的需求,需要不同的業(yè)務(wù)行為,函數(shù)式編程更多的是一種思路,在OO中沒(méi)有也不需要一定的成法。
不過(guò)這些實(shí)踐也給了我們實(shí)踐一個(gè)模式。
?
一、回顧一下函數(shù)式編程的幾個(gè)特性:
1. 閉包計(jì)算和高階函數(shù)。
?? 函數(shù)本身是first class對(duì)象,閉包是起函數(shù)作用并可以像對(duì)象一樣操作的。
?? 高階函數(shù)是可以接受一個(gè)函數(shù)為參數(shù),并可以返回一個(gè)函數(shù)。?????
2. 延遲計(jì)算(lazy evaluation)
?? 不是在函數(shù)綁定時(shí)計(jì)算,而是在求值時(shí)計(jì)算。
3. 遞歸的計(jì)算機(jī)制????
4. 引用透明
??? 同樣的輸入返回同樣的結(jié)果,與上下文無(wú)關(guān)。????
5. 沒(méi)有副作用
??? 賦值后不能更改,既成為constant?????
?
二、OO世界中FP的身影。
The First:JDK下的FP?
1.??閉包計(jì)算的例子如:BigDecimal.add(…).add(…).multiply(…).substract(…)?
?????高階函數(shù)一個(gè)例子是:Collections和Comparator接口,Comparator的操作是個(gè)閉包操作, 而Collections的sort以它為參數(shù)。?
2.??沒(méi)有副作用的例子如下:?
?????BigDecimal.add(…).add(…).multiply(…).substract(…)?
?????String.subString(...)
?
The Second:DDD的Specification?
DDD一書提出了specification(chapter 10代碼就不貼了),不僅統(tǒng)一了Domain Model中不同的建模概念,而且應(yīng)用FP的閉包能力在specification讓人耳目一新。
?
The Third:CO編程?
CO編程的概念是ajoo在javaeye論壇上提出(http://forum.javaeye.com/viewtopic.php?t=15130)?。
在論戰(zhàn)中舉了logger和action兩個(gè)例子,都讓人看到了FP對(duì)系統(tǒng)開(kāi)發(fā)的過(guò)程和結(jié)構(gòu)巨大作用。?
??
BTW:buaawhl總結(jié)了functor的幾種組合情況(http://forum.javaeye.com/viewtopic.php?t=21533, 以下是簡(jiǎn)化版,略有修改)?
1. Functor組合 - Combinator, Pipe?
????Functor有多個(gè),參數(shù)只有一個(gè)。這一類的特點(diǎn)是,F(xiàn)unctor移動(dòng),參數(shù)不動(dòng)。?
2. 參數(shù)集合 - Visitor, Map, Filter, Reduce?
????這一類比較有趣。參數(shù)是多個(gè),是一個(gè)集合,F(xiàn)unctor可以是一個(gè)(也可能是多個(gè))。?
????這一類的特點(diǎn)是,F(xiàn)unctor不動(dòng),參數(shù)移動(dòng)。?
3. Functor組合,參數(shù)集合 - Curry, Factory Chain?
????最復(fù)雜的類型,就是這一類了。Functor移動(dòng),參數(shù)也移動(dòng)。?
????
關(guān)于Curry,是FP的另一個(gè)特性。?
舉個(gè)例子:F(x, y, z) = 2 * x + y - z。?
F(1, 2, 3) 用Curry的方式寫就是,f(1)(2)(3)。這是FP語(yǔ)法。?
由于FP下沒(méi)有成員變量,只好借用Curry + Closure來(lái)積累多個(gè)變量。?
換成類似于c, java, c#的語(yǔ)法來(lái)寫,就是Factory Chain的寫法。?
?????factory.generate(1).generate(2).generate(3);?
這里的關(guān)鍵是,上一個(gè)Functor處理參數(shù)的結(jié)果產(chǎn)生了下一個(gè)Functor,下一個(gè)Functor繼續(xù)處理下一個(gè)參數(shù),產(chǎn)生下一個(gè)Functor。?
如java世界中著名的orm框架hibernate的criteria和Query:SessionFactory.newSession(..).newQuery(…).setParameter(…).setParameter(…)?
等等形式,都具有Curry, Factory Chain的形式特點(diǎn)。雖然有時(shí)候,F(xiàn)unctor返回的是自己。
?
The Four and so on?
還不知道,但相信還有更多。
?
三、回顧小結(jié)應(yīng)用現(xiàn)狀:?
1. JDK和Hibernate的設(shè)計(jì)提高了開(kāi)發(fā)過(guò)程的體驗(yàn),還沒(méi)有對(duì)系統(tǒng)開(kāi)發(fā)有大的影響(或許我的認(rèn)識(shí)還太過(guò)于膚淺)?
2. 而DDD的例子,則實(shí)踐了FP的閉包。封裝了對(duì)返回值的操作能力,相當(dāng)于specification的and,or和not包裝了對(duì)操作符調(diào)用。?
??
BTW:DDD例子中,不同的函數(shù)組合后共同操作相同輸入?yún)?shù)。實(shí)踐中還會(huì)出現(xiàn)不同函數(shù)組合在一起,但各自有各自的輸入?yún)?shù)。對(duì)于可能存在的Pipe組合,使得操作值和返回值是同一類型,相當(dāng)于functor包裝了操作符。?
??
3. ajoo的CO例子實(shí)踐了FP的高階函數(shù)(實(shí)踐后看上去像Decorate模式,不過(guò)出發(fā)點(diǎn)不一樣)。?
封裝了對(duì)流程的控制的能力,提供sequenue和pipe等的計(jì)算能力。這樣的設(shè)計(jì)要求開(kāi)發(fā)者明確了解對(duì)高階函數(shù)和輸入函數(shù)的關(guān)系。另外CO沒(méi)有提供閉包能力。?
??
無(wú)論如何,現(xiàn)有的幾個(gè)實(shí)踐:JDK,hibernate,ajoo的例子和DDD的例子都說(shuō)明了:
基于不同的需求,需要不同的業(yè)務(wù)行為,函數(shù)式編程更多的是一種思路,在OO中沒(méi)有也不需要一定的成法。
不過(guò)這些實(shí)踐也給了我們實(shí)踐一個(gè)模式。
[引用提示]幸福引用了該文章, 地址: http://www.cnweblog.com/maomao2008/archive/2008/01/07/269994.html