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