2008年6月13日 星期五

蔡學鏞【言程序】部落格: 思考函數編程(三)FP is as FP does

蔡學鏞【言程序】部落格: 思考函數編程(三)FP is as FP does

到底FP有哪些常見的特色?阿甘(Forrest Gump)說過「Stupid is as stupid does」。這個句型相當好用,套用到FP,就是「FP is as FP does」。我們可以透過FP作了些什麼(does),來瞭解FP是什麼(is)。


【Higher-Order Functions】某函數如果可以接受函數當作參數,或者以函數為傳出值,我們就稱這樣的函數為「較高次方函數」(Higher-Order Function)。較高次方函數讓程式可以變得相當有彈性,而且寫法比OOP更精簡許多。函數式語言有相當大的威力來自較高次方函數,特別是函數式語言 的程式庫往往會有許多較高次方函數,可以幫助你進行資料處理(例如特殊排序法、資料對應、資料過濾)、事件處理。


【Currying】 程式庫往往將函數定義得比較一般化,具有通用性。這樣的函數,需要傳入比較多的參數。利用Currying的方式,可以定義出「特殊化」的函數,這樣的特 殊化函數將函數的局部參數先指定好,只有剩下一部份參數沒有指定。例如,程式庫有個函數為power(x, y),會計算出x的y次方,那麼我們可用很簡單的語法,定義一個平方函數square(x),事先將參數y指定為2;且定義立方函數cubic(x),事 先將參數y指定為3。當然非函數式語言也做得到這一點,但不可能像函數式語言的語法這麼精簡。


【Lazy Evaluation】表示式的執行可以拖延到真正需要執行時才執行,這就是Lazy Evaluation。好處是可以讓編譯器有最大的優化空間(敘述的次序可以先後調動)、執行時可以符合當時最新的狀況、方便做出更高階的抽象結構、定義 無窮大的資料結構。上述的這些優點,如果不透過Lazy Evaluation,都不太容易做到(甚至不可能做到)。


【Continuations】 利用Continuation,可以將一個函數的傳出值,傳進另一個函數當作傳入值,也可以產生循序執行的效果。利用continuation的方式,可 以讓原本沒有狀態的技術,有了狀態,讓應用更好寫。利用Web原本是無狀態的,如果將Continuation用到Web的開發上,會使得開發變得容易許 多。


【Pattern Matching】模式比對的方式,可以讓系統自動幫我們進行分支(branch),與變數的指定(assignment)。有了模式比對,FP可以降低 依賴(imperative語言的)switch/case與(物件導向語言的)多型,而且寫出來的程式碼也不會像switch/case那樣一大塊。


【Closure】Closure讓函數在離開之後,其context依然保留(而不會像call stack內的frame一樣,被丟棄)。有了Closure,就可以設計「傳出值是函數」的函數。


【List Processing】FP的始祖語言LISP,名稱的意思正是List Processing,目的是要進行方便的List處理(List是資料的集合)。許多函數式語言都有好用的List處理語法(例如List Comprehensions、取出List頭部元素、插入List頭部)與Lisp處理函數(例如map、filter)。


【Meta-Programming】許多FP語言都可以有提供方便的Meta-Programming工具,讓你可以設計自己的DSL,來輔助軟體開發。


並 非所有的函數式語言都具有上述的特色。許多函數編程語言都不是「純的」函數語言,而是混合了相當多的imperative特性。學習函數編程時,如果使用 這些語言,可能比較無法體會到函數編程的意義。我鼓勵大家學習比較純的函數式語言,並多多使用它們的程式庫,這可以讓你對FP有比較深刻的體驗。(全文 完)

沒有留言: