函數式編程中的復合(compose)來自于數學,是定義在函數集合上的一種運算:對于任何兩個函數f:A→B和g:B→C,只要f的值域等于g的定義域,就可以做f和g的復合運算:
(g○f)(x)=g(f(x))
這樣,就得到一個新的函數g○f:A→C。
根據這個定義,在JavaScript中很容易就實現了復合運算:
測試一下:
OK!
雖然,函數復合看起了是一個很簡單的操作,不過有趣的是,很多支持函數式編程的語言(包括JavaScript),都不直接支持它。為什么呢?其原因是出在多元函數上,例如:
顯然,我們只能進行compose(neg,add)而不能進行compose(add,neg),因為,neg的值域是實數集R,而add的定義域事實上是實數集R的笛卡爾積R×R,它們不同不滿足復合運算的條件。
正是因為這個原因,那些以笛卡爾積方式實現多元函數的計算機語言多都不支持直接復合運算。
那么,只要是多元函數就不能參與復合嗎?當然不是!
雖然,最早多元函數被解釋為:以笛卡爾積作為其定義域的函數,例如:add:R×R→R,但后來ChristopherStrachey發現,多元函數也可以解釋為函數作用的形式,例如:add:R→(R→R),這個發現被柯里發揚廣大,于是稱這種解釋函數的方式為柯里化。
按照新的思路,將add寫成柯里化的形式:
然后測試一下,
OK!
一般來說,只要是支持函數復合運算的計算機語言,其函數的都被解釋為是柯里化的,例如:Haskell,F#等。
考慮到不能每次函數都寫兩個版本,所以需要有將笛卡爾積式的函數進行柯里化的函數,在JavaScript中其實現如下:
測試一下:
OK!