函數柯里化(Currying)和偏函數應用(Partial Application)的比較
英文原文:Currying vs. Partial Application
【名詞解釋】Currying:因為是美國數理邏輯學家哈斯凱爾·加里(Haskell Curry)發明了這種函數使用技巧,所以這樣用法就以他的名字命名為 Currying,中文翻譯為“柯里化”。
我感覺很多人都對函數柯里化(Currying)和偏函數應用(Partial Application)之間的區別搞不清楚,尤其是在相似的上下文環境中它們同時出現的時候。
偏函數解決這樣的問題:如果我們有函數是多個參數的,我們希望能固定其中某幾個參數的值。
幾乎所有編程語言中都有非常明顯的偏函數應用。在C語言中:
int foo (int a, int b, int c) {</span>return a + b + c; }int foo23(int a, int c) { return foo (a, 23, c);
}</span></pre></div>
foo23
函數實際上就是一個foo
函數的偏函數應用,參數b
的值被固定為 23。當然,像這樣明顯的偏函數并沒有太大的用處;我們通常會希望編程語言能提供我們某些偏函數特征。
例如,在 Python 語言中,我們可以這樣做:
from functools import partialdef foo (a,b,c):</span>return a + b + c
foo23 </span>= partial (foo, b=23)
foo23(a </span>= 1, c = 3) # => 27</pre></div>
函數柯里化(Currying)明顯解決的是一個完全不同的問題:如果我們有幾個單參數函數,并且這是一種支持一等函數(first-class)的語言,如何去實現一個多參數函數?函數柯里化是一種實現多參數函數的方法。
下面是一個單參數的 Javascript 函數:
var foo = function(a) {</span>return a * a; }</pre></div>
如果我們受限只能寫單參數函數,可以像下面這樣模擬出一個多參數函數:
var foo = function(a) {</span>return function(b) { return a a + b b;
} }</span></pre></div>
通過這樣調用它:
(foo (3))(4)
,或直接foo (3)(4)
。注意,函數柯里化提供了一種非常自然的方式來實現某些偏函數應用。如果你希望函數
foo
的第一個參數值被固定成5,你需要做的就是var foo5 = foo (5)
。這就 OK 了。函數foo5
就是foo
函數的偏函數。注意,盡管如此,我們沒有很簡單的方法對foo
函數的第二個參數偏函數化(除非先偏函數化第一個參數)。當然,Javascript 是支持多參數函數的:
var bar = function(a, b) {</span>return a a + b b;
}</span></pre></div>
我們定義的
bar
函數并不是一個柯里化的函數。調用bar (5)
并不會返回一個可以輸入 12 的函數。我們只能像bar (5,12)
這樣調用這個函數。在一些其它語言里,比如 Haskell 和 OCaml,所有的多參數函數都是通過柯里化實現的。
下面是一個把上面的
foo
函數用 OCaml 語言寫成的例子:let foo = fun a -> fun b -> a * a + b * b下面是把上面的
bar
函數用 OCaml 語言寫成的例子:let bar = fun a b -> a * a + b * b
頭一個函數我們叫做“顯式柯里化”,第二個叫做“隱式柯里化”。
跟 Javascript 不一樣,在 OCaml 語言里,
foo
函數和bar
函數是完全一樣的。我們用完全一樣的方式調用它們。# foo 3 4;;- : int = 25 # bar 3 4;;- : int = 25兩個函數都能夠通過提供一個參數值來創造一個偏函數:
# let foo5 = foo 5;; val foo5 : int -> int =# let bar5 = bar 5;; val bar5 : int -> int = # foo5 12;;- : int = 169 # bar5 12;;- : int = 169 事實上,我們可以把下面這個匿名函數:
fun arg1 arg2 ... argN -> exp當作是下面這個函數的簡寫:
fun arg1 -> fun arg2 -> ... -> fun argN -> exp函數柯里化和偏函數應用的總結
- 偏函數應用是找一個函數,固定其中的幾個參數值,從而得到一個新的函數。
- 函數柯里化是一種使用匿名單參數函數來實現多參數函數的方法。
- 函數柯里化能夠讓你輕松的實現某些偏函數應用。
- 有些語言(例如 Haskell, OCaml)所有的多參函數都是在內部通過函數柯里化實現的。
來自: 外刊IT評論
本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!相關資訊
相關經驗
sesese色