摘要:不純的函數(shù)充滿的不確定性,在函數(shù)式編程中要盡量避免它。在以后的函數(shù)式編程中還會不斷的遇見它的。
一.為什么需要柯里化(curry函數(shù))
1.先簡單的介紹一下純函數(shù)
在函數(shù)式編程中純函數(shù)是其最基本的思想,所謂純函數(shù)就是一個相對不受外界影響(之所以說相對,是因為有的時候需要和外界溝通,函數(shù)沒法保持所謂真正的純,但后面會有方法來解決).在高中數(shù)學(xué)中都學(xué)過,函數(shù)是一種映射關(guān)系,在y=f(x)這個函數(shù)式中,每一個x都有一個與之對應(yīng)的y值與它唯一對應(yīng)。
說了這么多好像還是不是很明白,那就來個簡單的例子:
//不純的 var num=18 function foo1(enter) { if (enter>18) { console.log("wow") } } //純的 function foo2(enter) { var num=18 if (enter>18) { console.log("wow") } }
兩個函數(shù)實現(xiàn)的效果其實是一樣的,但第一個函數(shù)不純,第二個函數(shù)才是真的純函數(shù),它將num定義在函數(shù)體內(nèi),外界無法直接獲取num,也無法改變它,相當(dāng)于打雷天縮到了被窩,外面雷再大也跟我沒關(guān)系了。
第一個函數(shù)之所以不純是因為,它引用了函數(shù)體外的一個變量num,一旦你進(jìn)行了外部引用,那這個函數(shù)的輸出就不確定了。一旦num被改變了,那這個函數(shù)就不會按照你希望的執(zhí)行下去了。不純的函數(shù)充滿的不確定性,在函數(shù)式編程中要盡量避免它。
純函數(shù)中還有很多的好處,再此就不展開討論了,以后有機(jī)會再詳細(xì)的說說。
2.純函數(shù)的一個使用場景
var add=x=>(y=>x+y)//為了更貼切函數(shù)式編程,這里用了ES6的寫法,等價于下面的函數(shù) // var add=function (x) { // return function(y) { // return x+y // } // } var add2=add(2) console.log(add2(1)) //3
這里使用閉包的方法,在add函數(shù)體內(nèi)返回的匿名函數(shù)中有這樣一句話:return x+y
它在匿名函數(shù)中保持著對x的引用,即使在垃圾回收中,x在執(zhí)行上下文中已經(jīng)被清理掉了,但還是能夠憑借引用找到它,這就是閉包應(yīng)用的簡單的解釋。
通過這樣的寫法,寫函數(shù)變得更加靈活了。add2實際接受到是一個匿名參數(shù),這個參數(shù)保留著第一次傳入的參數(shù)。但你所需要的所有參數(shù)都傳完(是的,可以有不止一個參數(shù),但需要通過curry函數(shù)的幫助),再執(zhí)行操作,也就是上述代碼中x+y操作。
這樣無論你想add10,還是add20,都很輕松了。
問題來了
這樣寫函數(shù)太挫了,而且太麻煩了,有沒有什么好辦法呢?答案是有,那就是今天的重頭戲curry函數(shù)(通過curry函數(shù)處理一個函數(shù)的過程也叫柯里化)
先上代碼:
//柯里函數(shù)實質(zhì):傳遞給函數(shù)一部分參數(shù)來調(diào)用它,讓它返回一個函數(shù)來處理剩余參數(shù) function curry(fx) { //要進(jìn)行柯里化的函數(shù)的形參數(shù)量 var arity=fx.length return function f1() { //第一次傳入的參數(shù)數(shù)量 var args=[].slice.call(arguments,0) //若傳入的參數(shù)數(shù)量大于等于形參數(shù)量,代表現(xiàn)在萬事俱備(參數(shù)齊全了),可以直接執(zhí)行函數(shù)了,直接將參數(shù)全部傳入fx函數(shù)中,并執(zhí)行它 if (args.length>=arity) { return fx.apply(null,args) }else{ var f2=function() { //如果只傳入了一部分參數(shù) var args2 = [].slice.call(arguments, 0) //判斷是否所有參數(shù)都傳完了,如果沒有,不斷concat新傳的參數(shù),然后執(zhí)行f1函數(shù) return f1.apply(null, args.concat(args2)) } return f2 } } }
其實看書看到這部分的時候作者直接用lodash庫中的curry,看的十分蛋疼,覺得沒有詳細(xì)的代碼總歸不能理解的透徹。結(jié)果點開github上的作業(yè)(這本書有習(xí)題,就在GitHub上),發(fā)現(xiàn)有curry函數(shù)的實現(xiàn)??戳艘蝗τ行┬〉牟惶斫獾牡胤叫薷牧艘幌拢闪爽F(xiàn)在看到的函數(shù)。
現(xiàn)在就可以用curry了,用起來也是十分舒服(偷懶直接上書上代碼):
var match = curry(function(what, str) { return str.match(what); }); var replace = curry(function(what, replacement, str) { return str.replace(what, replacement); }); var filter = curry(function(f, ary) { return ary.filter(f); }); var map = curry(function(f, ary) { return ary.map(f); }); match(/s+/g, "hello world"); // [ " " ] match(/s+/g)("hello world"); // [ " " ] var hasSpaces = match(/s+/g); // function(x) { return x.match(/s+/g) } hasSpaces("hello world"); // [ " " ] hasSpaces("spaceless"); // null filter(hasSpaces, ["tori_spelling", "tori amos"]); // ["tori amos"] var findSpaces = filter(hasSpaces); // function(xs) { return xs.filter(function(x) { return x.match( /s+/g) }) } findSpaces(["tori_spelling", "tori amos"]); // ["tori amos"]
這樣是不是就能感受到curry的強大之處呢。在以后的函數(shù)式編程中還會不斷的遇見它的。
(寫在最后,關(guān)于curry函數(shù)實現(xiàn)的一點小問題,使用ES6的箭頭函數(shù)更貼切函數(shù)式編程的思想,但是箭頭函數(shù)無法識別arguments對象,所以還是老老實實寫匿名函數(shù)把)
(本文屬于讀書筆記,看的書是js函數(shù)式編程,在gitbook上就能看到)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/89960.html
摘要:函數(shù)式編程,一看這個詞,簡直就是學(xué)院派的典范。所以這期周刊,我們就重點引入的函數(shù)式編程,淺入淺出,一窺函數(shù)式編程的思想,可能讓你對編程語言的理解更加融會貫通一些。但從根本上來說,函數(shù)式編程就是關(guān)于如使用通用的可復(fù)用函數(shù)進(jìn)行組合編程。 showImg(https://segmentfault.com/img/bVGQuc); 函數(shù)式編程(Functional Programming),一...
摘要:組合組合的功能非常強大,也是函數(shù)式編程的一個核心概念,所謂的對過程進(jìn)行封裝很大程度上就是依賴于組合。在理解之前,先認(rèn)識一個東西概念容器容器為函數(shù)式編程里普通的變量對象函數(shù)提供了一層極其強大的外衣,賦予了它們一些很驚艷的特性。 前言 JavaScript是一門多范式語言,即可使用OOP(面向?qū)ο螅?,也可以使用FP(函數(shù)式),由于筆者最近在學(xué)習(xí)React相關(guān)的技術(shù)棧,想進(jìn)一步深入了解其思想...
摘要:而函數(shù)式編程中,則認(rèn)為數(shù)據(jù)只是行為加工的產(chǎn)品。我們會發(fā)現(xiàn),在函數(shù)式編程中,我們?nèi)コ袅酥髡Z。下面就來說說函數(shù)式編程的一些具體的東西。純函數(shù)在函數(shù)式編程中,有一個很重要的概念是純函數(shù)。 JavaScript是一門很神奇的語言,作為一門現(xiàn)代化的語言,他有很多很有特色的東西,這些東西,讓我們看到了一個十分自由化的未來,你永遠(yuǎn)都不知道,自己是不是掌握了這門奇葩的要命的語言。本文,可能沒有那么多...
摘要:但是,對函數(shù)式編程而言,這個行為的重要性是毋庸置疑的。關(guān)于該模式更正式的說法是偏函數(shù)嚴(yán)格來講是一個減少函數(shù)參數(shù)個數(shù)的過程這里的參數(shù)個數(shù)指的是希望傳入的形參的數(shù)量。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 關(guān)于譯者:這是一個流淌著滬江血液的純粹工程:認(rèn)真,是 HTML 最堅實的梁柱;分享,是...
摘要:譯者團(tuán)隊排名不分先后阿希冬青蘿卜萌萌輕量級函數(shù)式編程第章融會貫通現(xiàn)在你已經(jīng)掌握了所有需要掌握的關(guān)于輕量級函數(shù)式編程的內(nèi)容?;仡^想想我們用到的函數(shù)式編程原則。這兩個函數(shù)組合成一個映射函數(shù)通過,這就是融合見第章。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 關(guān)于譯者:這是一個流淌著滬江血液的純粹工程:...
閱讀 3129·2021-11-08 13:18
閱讀 2276·2019-08-30 15:55
閱讀 3602·2019-08-30 15:44
閱讀 3063·2019-08-30 13:07
閱讀 2774·2019-08-29 17:20
閱讀 1942·2019-08-29 13:03
閱讀 3403·2019-08-26 10:32
閱讀 3218·2019-08-26 10:15