curry

Currying?is an advanced technique of working with functions. It’s used not only in JavaScript, but in other languages as well.

Currying is a transformation of functions that translates a function from callable as?f(a, b, c)?into callable as?f(a)(b)(c).

Currying doesn’t call a function. It just transforms it.

https://javascript.info/currying-partials

As you can see, the implementation is straightforward: it’s just two wrappers.

The result of?curry(func)?is a wrapper?function(a).

When it is called like?curriedSum(1), the argument is saved in the Lexical Environment, and a new wrapper is returned?function(b).

Then this wrapper is called with?2?as an argument, and it passes the call to the original?sum.


Currying is a pattern where a function with more than one parameter is broken into multiple functions that, when called in series, will accumulate all of the required parameters one at a time. This technique can be useful for making code written in a functional style easier to read and compose. It's important to note that for a function to be curried, it needs to start out as one function, then broken out into a sequence of functions that each accepts one parameter.


// here ...args collects arguments as array (rest)

// Here we check if current args passed equals the number of args func expects

// if yes, we spread args elements to pass into func (spread). This is our base case.

/* if not, we return a function that collects the next arguments passed in next and we recursively call curriedFunc, accumalating and spreading the values of args first and then the values of next. next will take into consideration a variable amount of next arguments e.g (1, 2) (1) (1,2,3) */

function curry(func){

? ? return function curriedFunc(...args){

? ? ? ? if(args.length>=func.length){

? ? ? ? ? ? return func(...args)

????????}else{

????????????return function(...next){

????????????????return curriedFunc(...args,...next);

????????????}

????????}

????}

}

const join=(a,b,c)=>{return`${a}_$潦闲_${c}`}

const curriedJoin=curry(join)

curriedJoin(1, 2, 3) // '1_2_3'

curriedJoin(1)(2, 3) // '1_2_3'

curriedJoin(1,2)(3)// '1_2_3'

function curry(func){

????return function curried(...args){

????????const complete=args.length>=func.length

????????????&&!args.slice(0,func.length).includes(curry.placeholder);

????????if(complete) return func.apply(this,args)

????????return function(...newArgs){

// replace placeholders in args with values from newArgs

const res=args.map(arg=>arg===curry.placeholder&&newArgs.length?newArgs.shift():arg);

????????return curried(...res,...newArgs);

????????}

????}

}

curry.placeholder=Symbol()


Function: length

The?length?data property of a?Function?instance indicates the number of parameters expected by the function.

function curry(fn){

????return function curryInner(...args){

????????if(args.length>=fn.length) return fn(...args);

????????return(...args2)=>curryInner(...args,...args2);

????};

}

currying:在一個(gè)函數(shù)中填充預(yù)參數(shù)昔头,再返回一個(gè)新函數(shù)
將預(yù)填充參數(shù)轉(zhuǎn)移到返回的新參數(shù)中
創(chuàng)造原始函數(shù)和參數(shù)的閉包

reference:https://cloud.tencent.com/developer/article/1431398

柯里化,又稱部分求值,一個(gè)currying的函數(shù)首先會(huì)接受一些參數(shù)哺壶,接受這些部分參數(shù)后,函數(shù)并不會(huì)立即求值横殴,而是繼續(xù)返回另一個(gè)函數(shù)昆禽,部分參數(shù)在函數(shù)形成的閉包中被保存起來,待到函數(shù)被真正需要求值的時(shí)候择卦,之前傳入的所有參數(shù)都會(huì)被一次性用于求值敲长。

柯里化的作用就是將普通函數(shù)轉(zhuǎn)變成高階函數(shù),實(shí)現(xiàn)動(dòng)態(tài)創(chuàng)建函數(shù)秉继、延遲計(jì)算祈噪、參數(shù)復(fù)用等作用。

把接受多個(gè)參數(shù)的函數(shù)變換成接受一個(gè)單一參數(shù)(最初函數(shù)的第一個(gè)參數(shù))的函數(shù)尚辑,并且返回接受余下的參數(shù)而且返回結(jié)果的新函數(shù)的技術(shù)辑鲤。

fn(1, 2, 3, 4) -> fn(1)(2)(3)(4)()

假設(shè)這個(gè)函數(shù)是用于求和,那么就是把本來接收多個(gè)參數(shù)一次性求和的函數(shù)改成了接收單一參數(shù)逐個(gè)求和的函數(shù)杠茬,這樣是不是容易理解了月褥。


currying函數(shù): 判斷傳入的參數(shù)長(zhǎng)度是否為0,若為0執(zhí)行函數(shù)瓢喉,否則收集參數(shù)到args數(shù)組宁赤;另一種常見的應(yīng)用是bind函數(shù)。

example1:

// 通用currying函數(shù)栓票,接受一個(gè)參數(shù)fn(即要被currying的函數(shù))

var currying = function(fn) {

? ? var args = [];

? ? return function curried() {

? ? ? ? if (arguments.length === 0) {

? ? ? ? ? ? return fn.apply(this, args);

? ? ? ? } else {

? ? ? ? ? ? [].push.apply(args, arguments);

? ? ? ? ? ? return arguments.callee;

? ? ? ? }

? ? }

};

// 將被currying的函數(shù)

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 );? ? // 轉(zhuǎn)化成currying函數(shù)

cost( 100 );? ? // 未真正求值

cost( 200 );? ? // 未真正求值

cost( 300 );? ? // 未真正求值

console.log (cost());? ? // 求值并輸出:600


example2:

實(shí)現(xiàn)上就是返回一個(gè)高階函數(shù)决左,通過閉包把傳入的參數(shù)保存起來。當(dāng)傳入的參數(shù)數(shù)量不足時(shí),遞歸調(diào)用bind方法哆窿;數(shù)量足夠時(shí)則立即執(zhí)行函數(shù)链烈。

function curry(fn){

????const len=fn.length;

????return function curried(...args){

????????if(args.length<len){

????????????return curried.bind(null,...args);

????????}

????????return fn.apply(null,args);

????}

}


ES6極簡(jiǎn)寫法

const currying = fn =>?

? ? curried = (...args1) =>?

????????args1.length>=fn.length

????????? fn(...args1)?

????????: (...args2) => curried(...args1,...args2)

fn.length表示函數(shù)的所有參數(shù)個(gè)數(shù)嗎?不是挚躯,函數(shù)的length屬性獲取的是形參的個(gè)數(shù)


如果很難理解强衡,看下面例子:

function currying(fn,length){

????length=length || fn.length;

????return function(...args){

????????return args.length>=length

?????????????fn.apply(this,args)

????????????:currying(fn.bind(this,...args),length-args.length)

????}

}


JS的API哪些應(yīng)用到了函數(shù)柯里化的實(shí)現(xiàn)?

實(shí)現(xiàn)一個(gè)sum函數(shù)码荔,sum(1,2)(3).valueOf()這樣調(diào)用后的結(jié)果為6


function?sum(...rest){

????let args=?[...rest];


????const?f?=?function(...others){

????????args=?args.concat(others);

????????return?f;

????};


????f.valueOf?=?function()?{

????????let?result?=?0;

????????for(let?val?of?args)?{

????????????result?+=?val;

????????}

????????return?result;

????}


????return?f;

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末漩勤,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子缩搅,更是在濱河造成了極大的恐慌越败,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,451評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件硼瓣,死亡現(xiàn)場(chǎng)離奇詭異究飞,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)堂鲤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門亿傅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人瘟栖,你說我怎么就攤上這事葵擎。” “怎么了半哟?”我有些...
    開封第一講書人閱讀 164,782評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵酬滤,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我寓涨,道長(zhǎng)盯串,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,709評(píng)論 1 294
  • 正文 為了忘掉前任戒良,我火速辦了婚禮嘴脾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蔬墩。我一直安慰自己译打,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評(píng)論 6 392
  • 文/花漫 我一把揭開白布拇颅。 她就那樣靜靜地躺著奏司,像睡著了一般。 火紅的嫁衣襯著肌膚如雪樟插。 梳的紋絲不亂的頭發(fā)上韵洋,一...
    開封第一講書人閱讀 51,578評(píng)論 1 305
  • 那天竿刁,我揣著相機(jī)與錄音,去河邊找鬼搪缨。 笑死食拜,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的副编。 我是一名探鬼主播负甸,決...
    沈念sama閱讀 40,320評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼痹届!你這毒婦竟也來了呻待?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,241評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤队腐,失蹤者是張志新(化名)和其女友劉穎蚕捉,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體柴淘,經(jīng)...
    沈念sama閱讀 45,686評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡迫淹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了为严。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片敛熬。...
    茶點(diǎn)故事閱讀 39,992評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖梗脾,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情盹靴,我是刑警寧澤炸茧,帶...
    沈念sama閱讀 35,715評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站稿静,受9級(jí)特大地震影響梭冠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜改备,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評(píng)論 3 330
  • 文/蒙蒙 一控漠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧悬钳,春花似錦盐捷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至母剥,卻和暖如春滞诺,著一層夾襖步出監(jiān)牢的瞬間形导,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工习霹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留朵耕,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,173評(píng)論 3 370
  • 正文 我出身青樓淋叶,卻偏偏與公主長(zhǎng)得像阎曹,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子爸吮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 柯里化(Currying) 是把接受多個(gè)參數(shù)的函數(shù)變換成接受一個(gè)單一參數(shù)(最初函數(shù)的第一個(gè)參數(shù))的函數(shù)芬膝,并且返回接...
    lotawei閱讀 286評(píng)論 0 0
  • 一、什么是Currying 定義:柯里化(Currying)是把接受多個(gè)參數(shù)的函數(shù)變換成接受一個(gè)單一參數(shù)(最初函數(shù)...
    劉越姐姐啊閱讀 893評(píng)論 0 0
  • 參考鏈接:http://www.reibang.com/p/b80e13e4e5de 概念:在計(jì)算機(jī)科學(xué)中形娇,柯里...
    90后的晨仔閱讀 400評(píng)論 0 2
  • 一. Currying解釋 currying 翻譯為局部套用.又稱為部分求值(Partial Evaluation...
    Mccc_閱讀 1,545評(píng)論 0 4
  • “我10號(hào)锰霜,你18號(hào)⊥┰纾”衛(wèi)墨了然地看向柒月癣缅。 “對(duì)『逶停”柒月只剩下小雞啄米般頻頻點(diǎn)頭友存。 “背一遍稿子給我聽√招疲”衛(wèi)墨說...
    趁早退場(chǎng)閱讀 254評(píng)論 8 5