亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

currying和部分應用有什么區別?

currying和部分應用有什么區別?

currying和部分應用有什么區別?我經常在互聯網上看到各種各樣的抱怨,其他人的currying例子并不是currying,但實際上只是部分應用。我沒有找到關于部分應用是什么的合理解釋,或者它與currying有何不同。似乎存在普遍的混淆,在某些地方將等效的例子描述為currying,在其他地方描述為部分應用。有人可以向我提供這兩個術語的定義,以及它們如何區別的細節嗎?
查看完整描述

3 回答

?
慕仙森

TA貢獻1827條經驗 獲得超8個贊

Currying將n個參數的單個函數轉換為n個函數,每個函數都有一個參數。鑒于以下功能:


function f(x,y,z) { z(x(y));}

咖喱變成:


function f(x) { lambda(y) { lambda(z) { z(x(y)); } } }

為了獲得f(x,y,z)的完整應用,您需要這樣做:


f(x)(y)(z);

許多函數式語言都可以讓你寫f x y z。如果你只調用f x y或f(x)(y)那么你得到一個部分應用的函數 - 返回值是一個閉包,lambda(z){z(x(y))}傳入x和y的值f(x,y)。


使用部分應用程序的一種方法是將函數定義為廣義函數的部分應用程序,如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


查看完整回答
反對 回復 2019-08-06
?
汪汪一只貓

TA貢獻1898條經驗 獲得超8個贊

了解它們之間差異的最簡單方法是考慮一個真實的例子。假設我們有一個函數Add,它將2個數字作為輸入并返回一個數字作為輸出,例如Add(7, 5)返回12。在這種情況下:

  • 使用Add部分應用函數7將為我們提供一個新函數作為輸出。該函數本身需要1個數字作為輸入并輸出一個數字。因此:

    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會給我們一個新的功能輸出。該功能本身需要1號作為輸入,并輸出另一個新的功能。然后第三個函數將1個數作為輸入并返回一個數作為輸出。因此:

    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”是兩個完全不同的功能。Currying只需1個輸入,而部分應用需要2個(或更多)輸入。

即使它們都返回一個函數作為輸出,返回的函數也是完全不同的形式,如上所示。


查看完整回答
反對 回復 2019-08-06
?
GCT1015

TA貢獻1827條經驗 獲得超4個贊

注意:這是從F#Basics中獲取的,這是.NET開發人員進入函數式編程的優秀介紹性文章。

Currying意味著將具有許多參數的函數分解為一系列函數,每個函數都接受一個參數并最終產生與原始函數相同的結果。對于功能編程新手來說,Currying可能是最具挑戰性的話題,特別是因為它經常與部分應用混淆。您可以在此示例中看到兩者都在工作:

let multiply x y = x * y    let double = multiply 2let ten = double 5

您應該立即看到與大多數命令式語言不同的行為。第二個語句通過將一個參數傳遞給一個帶兩個的函數來創建一個名為double的新函數。結果是一個函數,它接受一個int參數并產生相同的輸出,就好像你已經調用了multiply,x等于2,y等于那個參數。在行為方面,它與此代碼相同:

let double2 z = multiply 2 z

通常,人們錯誤地認為乘法是形成雙重的。但這只是有點真實。乘法函數是curry,但是在定義時會發生這種情況,因為默認情況下F#中的函數是curry。當創建雙重函數時,更準確地說,部分應用了乘法函數。

乘法函數實際上是一系列兩個函數。第一個函數接受一個int參數并返回另一個函數,有效地將x綁定到特定值。此函數還接受一個int參數,您可以將其視為綁定到y的值。在調用第二個函數之后,x和y都被綁定,因此結果是x和y的乘積,如double體中所定義。

要創建double,將計算乘法函數鏈中的第一個函數以部分應用乘法。結果函數的名稱為double。當計算double時,它使用其參數以及部分應用的值來創建結果。


查看完整回答
反對 回復 2019-08-06
  • 3 回答
  • 0 關注
  • 544 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號