高階函數
個人理解就是將函數作爲參數的嵌套函數編寫方式,這樣寫的好處是邏輯會變的很清晰。
Currying(柯里化)
從書從直觀的感受就是將一個大函數分解爲多個函數共同處理的方式,目的是爲了減少函數參數的數量,快速封裝函數。例:
int pow(int i, int j);
int square(int i)
{
return pow(i, 2);
}
惰性求值
在函數式編程的大環境下,代碼塊是可以併發執行的,但有時候不需要併發執行,甚至於有時候只需要併發程序中的一個或者兩個執行就行了,那麼爲了不浪費那麼多的資源,在函數式編程中程序不需要順序執行,只有等函數需要調用併發程序的時候再去運行該程序,這樣的函數執行方式叫做惰性求值。
- 代碼優化
因爲函數在有需求的情況下才會被調用的原因,所以存在着很多優化的方式和可能,比如在代碼執行順序上作出調整,去掉重複的運算單元
- 抽象化控制結構
unless(stock.isEuropean()) {
sendToSEC(stock);
}
void unless(boolean condition, List code) {
if(!condition)
code;
}
這裏的控制結構可以理解爲js裏的回調函數,參數中的函數不會立即執行,需要在代碼中執行時纔會運行。
- 不足之處
如果涉及到鍵盤或者其他輸入交互時,惰性求值的弊端就出現了,因無法保證程序能夠順序執行代碼。
爲了保證程序的函數式執行,又要保證鍵盤等輸入的可控性,所以引入了Continuation指令式編程
-
Continuation
通常講函數一定需要將返回值返回給調用者,但是Continuation的引入,函數可以不把函數值返回給調用者,而是允許返回給程序中的任意代碼,簡單舉例如下
//正常寫法
int i = add(5, 10);
int j = square(i);
//cps寫法
int j = add(5, 10, square);
使用cps(Continuation Pass Style)寫法時,在add中多一個參數,這保證必須將計算的結果傳入square中。因爲在這個編寫過程中具有依賴關係了。
模式匹配
匹配模式主要適應的場景是在有很多判斷分支,或者實現複雜的嵌套語句時,匹配模式會將複雜的分支或者嵌套更好的拆分多個新函數
閉包(Closure)
先上例子,我將c的程序用js重新寫了一下:
function pow(a,b){
return a*b
}
function makePowerFn(power) {
function powerFn( base){
return pow(base,power)
}
return powerFn
}
var square = makePowerFn(2);
console.log(square(3))//6
這裏使用的maPowerFn傳入參數2時,square函數返回了另一個函數,我們直接調用square函數,便可以得到想要的結果,但問題出現:power傳的參數不在powerFn函數的域內,因爲makePowerFn已經返回結果了,所以棧也就不存在了。
那麼suqare是如何工作的?這個時候需要語言通過某種方式支持繼續存儲power的值,以便square後面繼續使用。那麼如果再定義一個函數,cube,用來計算立方,又應該怎麼做呢?那麼運行中的程序就必須存儲兩份power的值,提供給makePowerFn生成的兩個函數分別使用。這種保存變量值的方法就叫做closure。closure不僅僅保存宿主函數的參數值,還可以用在下例的用法中:
var makeIncrement = () => {
var i = 0
return increment = () =>{
return ++i
}
}
var demo1 = makeIncrement()
var demo2 = makeIncrement()
console.log(demo1(),demo1(),demo1())//1,2,3
console.log(demo2(),demo2(),demo2())//1,2,3
程序運行不僅會存儲i的值,以便後續程序訪問,也會個i做無限個拷貝