3 回答

TA貢獻(xiàn)1827條經(jīng)驗(yàn) 獲得超8個(gè)贊
Currying將n個(gè)參數(shù)的單個(gè)函數(shù)轉(zhuǎn)換為n個(gè)函數(shù),每個(gè)函數(shù)都有一個(gè)參數(shù)。鑒于以下功能:
function f(x,y,z) { z(x(y));}
咖喱變成:
function f(x) { lambda(y) { lambda(z) { z(x(y)); } } }
為了獲得f(x,y,z)的完整應(yīng)用,您需要這樣做:
f(x)(y)(z);
許多函數(shù)式語言都可以讓你寫f x y z。如果你只調(diào)用f x y或f(x)(y)那么你得到一個(gè)部分應(yīng)用的函數(shù) - 返回值是一個(gè)閉包,lambda(z){z(x(y))}傳入x和y的值f(x,y)。
使用部分應(yīng)用程序的一種方法是將函數(shù)定義為廣義函數(shù)的部分應(yīng)用程序,如fold:
function fold(combineFunction, accumulator, list) {/* ... */}
function sum = curry(fold)(lambda(accum,e){e+accum}))(0);
function length = curry(fold)(lambda(accum,_){1+accum})(empty-list);
function reverse = curry(fold)(lambda(accum,e){concat(e,accum)})(empty-list);
/* ... */
@list = [1, 2, 3, 4]
sum(list) //returns 10
@f = fold(lambda(accum,e){e+accum}) //f = lambda(accumulator,list) {/*...*/}
f(0,list) //returns 10
@g = f(0) //same as sum
g(list) //returns 10

TA貢獻(xiàn)1898條經(jīng)驗(yàn) 獲得超8個(gè)贊
了解它們之間差異的最簡單方法是考慮一個(gè)真實(shí)的例子。假設(shè)我們有一個(gè)函數(shù)Add
,它將2個(gè)數(shù)字作為輸入并返回一個(gè)數(shù)字作為輸出,例如Add(7, 5)
返回12
。在這種情況下:
使用
Add
值部分應(yīng)用函數(shù)7
將為我們提供一個(gè)新函數(shù)作為輸出。該函數(shù)本身需要1個(gè)數(shù)字作為輸入并輸出一個(gè)數(shù)字。因此:Partial(Add, 7); // returns a function f2 as output // f2 takes 1 number as input and returns a number as output
所以我們可以這樣做:
f2 = Partial(Add, 7);f2(5); // returns 12; // f2(7)(5) is just a syntactic shortcut
嘩眾取寵的功能
Add
會(huì)給我們一個(gè)新的功能輸出。該功能本身需要1號(hào)作為輸入,并輸出又另一個(gè)新的功能。然后第三個(gè)函數(shù)將1個(gè)數(shù)作為輸入并返回一個(gè)數(shù)作為輸出。因此:Curry(Add); // returns a function f2 as output // f2 takes 1 number as input and returns a function f3 as output // i.e. f2(number) = f3 // f3 takes 1 number as input and returns a number as output // i.e. f3(number) = number
所以我們可以這樣做:
f2 = Curry(Add);f3 = f2(7);f3(5); // returns 12
換句話說,“currying”和“partial application”是兩個(gè)完全不同的功能。Currying只需1個(gè)輸入,而部分應(yīng)用需要2個(gè)(或更多)輸入。
即使它們都返回一個(gè)函數(shù)作為輸出,返回的函數(shù)也是完全不同的形式,如上所示。

TA貢獻(xiàn)1827條經(jīng)驗(yàn) 獲得超4個(gè)贊
注意:這是從F#Basics中獲取的,這是.NET開發(fā)人員進(jìn)入函數(shù)式編程的優(yōu)秀介紹性文章。
Currying意味著將具有許多參數(shù)的函數(shù)分解為一系列函數(shù),每個(gè)函數(shù)都接受一個(gè)參數(shù)并最終產(chǎn)生與原始函數(shù)相同的結(jié)果。對(duì)于功能編程新手來說,Currying可能是最具挑戰(zhàn)性的話題,特別是因?yàn)樗?jīng)常與部分應(yīng)用混淆。您可以在此示例中看到兩者都在工作:
let multiply x y = x * y let double = multiply 2let ten = double 5您應(yīng)該立即看到與大多數(shù)命令式語言不同的行為。第二個(gè)語句通過將一個(gè)參數(shù)傳遞給一個(gè)帶兩個(gè)的函數(shù)來創(chuàng)建一個(gè)名為double的新函數(shù)。結(jié)果是一個(gè)函數(shù),它接受一個(gè)int參數(shù)并產(chǎn)生相同的輸出,就好像你已經(jīng)調(diào)用了multiply,x等于2,y等于那個(gè)參數(shù)。在行為方面,它與此代碼相同:
let double2 z = multiply 2 z通常,人們錯(cuò)誤地認(rèn)為乘法是形成雙重的。但這只是有點(diǎn)真實(shí)。乘法函數(shù)是curry,但是在定義時(shí)會(huì)發(fā)生這種情況,因?yàn)槟J(rèn)情況下F#中的函數(shù)是curry。當(dāng)創(chuàng)建雙重函數(shù)時(shí),更準(zhǔn)確地說,部分應(yīng)用了乘法函數(shù)。
乘法函數(shù)實(shí)際上是一系列兩個(gè)函數(shù)。第一個(gè)函數(shù)接受一個(gè)int參數(shù)并返回另一個(gè)函數(shù),有效地將x綁定到特定值。此函數(shù)還接受一個(gè)int參數(shù),您可以將其視為綁定到y(tǒng)的值。在調(diào)用第二個(gè)函數(shù)之后,x和y都被綁定,因此結(jié)果是x和y的乘積,如double體中所定義。
要?jiǎng)?chuàng)建double,將計(jì)算乘法函數(shù)鏈中的第一個(gè)函數(shù)以部分應(yīng)用乘法。結(jié)果函數(shù)的名稱為double。當(dāng)計(jì)算double時(shí),它使用其參數(shù)以及部分應(yīng)用的值來創(chuàng)建結(jié)果。
添加回答
舉報(bào)