日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

柯里化详解

發布時間:2023/12/13 综合教程 29 生活家
生活随笔 收集整理的這篇文章主要介紹了 柯里化详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在計算機科學中,柯里化(Currying)是把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數,并且返回接受余下的參數且返回結果的新函數的技術。這個技術由 Christopher Strachey 以邏輯學家 Haskell Curry 命名的,盡管它是 Moses Schnfinkel 和 Gottlob Frege 發明的。

柯里化(Currying)指的是將原來接受兩個參數的函數變成新的接受一個參數的函數的過程。新的函數返回一個以原有第二個參數為參數的函數。

柯里化是很多高級編程語言擁有的特性,比如:JS、scala。

柯里化的好處:
1、參數復用。
2、提前返回。
3、 延遲計算/運行。

函數柯里化(currying)又稱部分求值。一個 currying 的函數首先會接受一些參數,接受了這些參數之后,該函數并不會立即求值,而是繼續返回另外一個函數,剛才傳入的參數在函數形成的閉包中被保存起來。待到函數被真正需要求值的時候,之前傳入的所有參數都會被一次性用于求值。

例如:
有一個函數,功能是計算每月的開銷,我們實際關心的是整個月的開銷總額。

var monthlyCost = 0;
var cost = function( money ){
monthlyCost += money;
};
cost( 100 ); // 第 1 天開銷
cost( 200 ); // 第 2 天開銷
cost( 300 ); // 第 3 天開銷
//cost( 700 ); // 第 30 天開銷
alert ( monthlyCost ); // 輸出:600

通過這段代碼可以看到,每天結束后我們都會記錄并計算到今天為止花掉的錢。但我們其實并不太關心每天花掉了多少錢,而只想知道到月底的時候會花掉多少錢。也就是說,實際上只需要在月底計算一次。
如果在每個月的前 29 天,我們都只是保存好當天的開銷,直到第 30 天才進行求值計算,這樣就達到了我們的要求。雖然下面的 cost 函數還不是一個 currying 函數的完整實現,但有助于我們了解其思想:

var cost = (function(){
var args = [];
return function(){
if ( arguments.length === 0 ){
var money = 0;
for ( var i = 0, l = args.length; i < l; i++ ){
money += args[ i ];
}
return money;
}else{
[].push.apply( args, arguments );
}
}
})();
cost( 100 ); // 未真正求值
cost( 200 ); // 未真正求值
cost( 300 ); // 未真正求值
console.log( cost() ); // 求值并輸出:600

柯里化的通用方式:

function curry(fn){
    var args=Array.prototype.slice.call(arguments,1);
    return function(){
        var innerArgs = Array.prototype.slice.call(arguments);
        var finalArgs = args.concat(innerArgs);
        return fn.apply(null,finalArgs);
    );
}
function add(n1,n2){
  return n1+n2;
}
var cur=curry(add,5)
alert(cur(3))

上面的代碼就完成了對add函數的柯理化,其原理十分簡單。無非就是把上一層傳入的參數再連接起來,傳回原來的多參數函數。第一步args代表的就是要保留的那個參數。

使用函數柯里化解決問題

var currying = function( fn ){ 
 var args = []; 
 return function(){ 
 if ( arguments.length === 0 ){ 
 return fn.apply( this, args ); 
 }else{ 
 [].push.apply( args, arguments ); 
 return arguments.callee; 
 } 
 } 
}; 
var cost = (function(){ 
 var money = 0; 
 return function(){ 
 for ( var i = 0, l = arguments.length; i < l; i++ ){ 
 money += arguments[ i ]; 
 } 
 return money; 
 } 
})(); 
var cost = currying( cost ); // 轉化成 currying 函數
cost( 100 ); // 未真正求值
cost( 200 ); // 未真正求值 
cost( 300 ); // 未真正求值
alert ( cost() ); // 求值并輸出:600 

至此,我們完成了一個 currying 函數的編寫。當調用 cost()時,如果明確地帶上了一些參數,表示此時并不進行真正的求值計算,而是把這些參數保存起來,此時讓 cost 函數返回另外一個函數。只有當我們以不帶參數的形式執行 cost()時,才利用前面保存的所有參數,真正開始進行求值計算。

Scala 中的柯里化

# 定義一個函數
函數1 :def add(x:Int,y:Int)=x+y
# 把函數變形:
函數2:def add(x:Int)(y:Int) = x + y
# 再變形:
函數3:def add(x:Int)=(y:Int)=>x+y

這3個函數在scala里都是支持的,函數1和函數2是普通函數,函數3是柯里化函數,我們看下執行上的區別:

# 函數1 :def add(x:Int,y:Int)=x+y
scala> def add(x:Int,y:Int)=x+y
add: (x: Int, y: Int)Int

scala> add(2,3)
res0: Int = 5

# 函數2:def add(x:Int)(y:Int) = x + y
scala> def add(x:Int)(y:Int)=x+y
add: (x: Int)(y: Int)Int

scala> add(2)(3)
res0: Int = 5

# 函數3:def add(x:Int)=(y:Int)=>x+y
scala> def add(x:Int)=(y:Int)=>x+y
add: (x: Int)Int => Int

scala> add(2)
res0: Int => Int = $$Lambda$1058/1404150776@7d97e06c

scala> add(3)
res1: Int => Int = $$Lambda$1058/1404150776@523a7801

scala> add(2)(3)
res2: Int = 5

通過上面的計算過程可以看出,函數3,也是需要傳2個參數的,如果傳了2個參數,馬上會計算出結果;如果只傳了一個參數,那么會生成一個臨時的結果res0,這里面并沒有把結果計算出來,而是把運算緩存起來了,當第二個參數也傳進來了,就會開始計算最終結果。

再舉上面的計算每月總開銷的例子,柯里化函數并不關心中間結果,也不會去計算中間結果,只會做一個緩存計算操作的操作,在最終需要執行的時候才去執行

如果你有更好的理解柯里化的方式,歡迎在評論區交流。

總結

以上是生活随笔為你收集整理的柯里化详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。