純函式和柯里化很容易寫出洋蔥** h(g(f(x))),就是乙個函式鑲嵌另乙個函式,多重組合,最終實現我們想要的功能,就像下面這個洋蔥一樣:
函式組合,就是利用多個函式,把細粒度的函式重新組合生成乙個新的函式,從而實現我們想要的邏輯。
比如:獲取陣列的最後乙個元素再轉換成大寫字母, .toupper(.first(_.reverse(array)))
管道
下面這張圖表示程式中使用函式處理資料的過程,給 fn 函式輸入引數 a,返回結果 b。可以想想 a 資料通過乙個管道得到了 b 資料:
當 fn 函式比較複雜的時候,我們可以把函式 fn 拆分成多個小函式,此時多了中間運算過程產生的 m 和 n。
下面這張圖中可以想象成把 fn 這個管道拆分成了3個管道 f1, f2, f3,資料 a 通過管道 f3 得到結果 m,m再通過管道 f2 得到結果 n,n 通過管道 f1 得到最終結果 b:
**形式簡單表現為:
fn =
compose
(f1, f2, f3)
b =fn
(a)
如果乙個函式要經過多個函式處理才能得到最終值,這個時候可以把中間過程的函式合併成乙個函式。
函式就像是資料的管道,函式組合就是把這些管道連線起來,讓資料穿過多個管道形成最終結果。
函式組合預設是從右到左執行:
// 組合函式
function
compose
(f, g)
}// 取首值
function
first
(arr)
// 反轉
function
reverse
(arr)
// 從右到左執行
let last =
compose
(first, reverse)
console.
log(
last([
1,2,
3,4]
))
函式的組合要滿足結合律 (associativity):我們既可以把 g 和 h 組合,還可以把 f 和 g 組合,結果都是一樣的:
// 結合律(associativity)
let f =
compose
(f, g, h)
let associative =
compose
(compose
(f, g)
, h)
==compose
(f,compose
(g, h)
)// true
到目前為止已經已經學習了函式式程式設計的一些基礎,但是我們還沒有演示在函式式程式設計中如何把***控制在可控的範圍內、異常處理、非同步操作等。
什麼是 functor
容器:包含值和值的變形關係(這個變形關係就是函式)。
函子:是乙個特殊的容器,通過乙個普通的物件來實現,該物件具有 map 方法,map 方法可以執行乙個函式對值進行處理(變形關係)。
functor 函子
// 乙個容器,包裹乙個值
class
container
constructor
(value)
// map 方法,傳入變形關係,將容器裡的每乙個值對映到另乙個容器
map(fn)
}// 測試
container.of(
3).map
(x => x +2)
.map
(x => x * x)
總結函式式程式設計的運算不直接操作值,而是由函子完成; 函子就是乙個實現了 map 契約的物件;
我們可以把函子想象成乙個盒子,這個盒子裡封裝了乙個值;
想要處理盒子中的值,我們需要給盒子的 map方法傳遞乙個處理值的函式(純函式),由這個函式來對值進行處理;
最終 map 方法返回乙個包含新值的盒子(函子)。
在 functor 中如果我們傳入 null 或 undefined:
// 值如果不小心傳入了空值(***)
container.of(
null).
map(x => x.
touppercase()
)// typeerror: cannot read property 'touppercase' of null
對錯誤進行處理,這就需要用到maybe函子了。
maybe 函子
我們在程式設計的過程中可能會遇到很多錯誤,需要對這些錯誤做相應的處理;
maybe 函子的作用就是可以對外部的空值情況做處理(控制***在允許的範圍)。
class
maybe
constructor
(value)
// 如果對空值變形的話直接返回 值為 null 的函子
map(fn)
isnothing()
}// 傳入具體值
maybe.of(
'hello world').
map(x => x.
touppercase()
)// 傳入 null 的情況
maybe.of(
null).
map(x => x.
touppercase()
)// => maybe
maybe 還是有個問題,就是我們很難確認是哪一步產生的空值問題,如下例:
maybe.of(
'hello world').
map(x => x.
touppercase()
).map(x =>
null).
map(x => x.
split
(' '))
// => maybe
either 函子either 兩者中的任何乙個,類似於 if…else…的處理,異常會讓函式變的不純,either 函子可以用來做異常處理:
class
left
constructor
(value)
map(fn)
}class
right
constructor
(value)
map(fn)
}
either 用來處理異常
function
parsejson
(json)
catch(e
));}
}let r =
parsejson(''
).map(x => x.name.
touppercase()
)console.
log(r)
函子的思想,還需多多體會和應用鍛鍊。 Js ES6函式式程式設計 函子
在正式學習函子之前,我會先丟擲乙個問題,先用普通的方式解決,然後轉換為用函子解決,這能幫助我們更好的理解函子。同時,這也是我想說的,在我們學習乙個新的知識點前,首先必須清楚為什麼會有它,或者說它是為了解決什麼問題而生的,這也是我們學習新知識後能夠快速達到學以致用的最有效方法,不然很容易被遺忘。fun...
python函式式程式設計模式 python函式式程式設計
1 callable內建函式判斷乙個名字是否為乙個可呼叫函式 import math x 1 y math.sqrt callable x false callable y true 2 記錄函式 文件字串 def square x calculates the square of number x...
python函式式程式設計模式 Python函式式程式設計
函式式程式設計就是一種抽象程度很高的程式設計正規化,純粹的函式式程式語言編寫的函式沒有變數,因此,任意乙個函式,只要輸入是確定的,輸出就是確定的,這種純函式我們稱之為沒有 而允許使用變數的程式語言,由於函式內部的變數狀態不確定,同樣的輸入,可能得到不同的輸出,因此,這種函式是有 的。函式式程式設計的...