函數(shù)式編程學(xué)習(xí)過程中的一些總結(jié)

最近在學(xué)習(xí)函數(shù)式編程,記錄了一些筆記岁忘,也總結(jié)了一些自己的理解辛慰。我準(zhǔn)備整理一下陸陸續(xù)續(xù)發(fā)出來,本文不算是一篇文章吧干像,算是自己在學(xué)習(xí)函數(shù)式編程中的一些總結(jié)帅腌,也算一個(gè)引子。

一些約束

  • 不要為了延遲執(zhí)行麻汰,而簡(jiǎn)單地用一個(gè)函數(shù)把另一個(gè)函數(shù)包起來速客。
  • 參數(shù)命名的時(shí)候,不要把參數(shù)名限制在特定的數(shù)據(jù)上五鲫,容易造成重復(fù)造輪子溺职。
  • 函數(shù)不依賴外部值

純函數(shù)

1.概念

函數(shù)式編程中函數(shù)是一等公民,即普通人。對(duì)于函數(shù)浪耘,強(qiáng)調(diào)純函數(shù)的概念智亮。什么是純函數(shù)呢?

純函數(shù)是這樣一種函數(shù)点待,相同的輸入阔蛉,永遠(yuǎn)會(huì)得到相同的輸出,而且沒有任何可觀察的副作用癞埠。

比較明顯的一個(gè)例子就是slice和splice状原。前者純而后者不純,想想為什么~

這里說的沒有副作用具體是什么呢苗踪?像上面我提到的splice颠区,它的副作用就是修改了本來的數(shù)據(jù),還有一些容易想到的情況通铲,如向數(shù)據(jù)庫插入了數(shù)據(jù)毕莱,打印了數(shù)據(jù),獲取了用戶輸入等颅夺。 總之朋截,就是一切跟函數(shù)外部環(huán)境反生交互的行為。

歸根結(jié)底吧黄,這些行為很容易導(dǎo)致“相同的輸入返回相同的結(jié)果”這一概念的失效部服。這也是我們盡量避開它們的原因。

2.為什么追求純拗慨?

為什么要花這么多力氣去實(shí)現(xiàn)純函數(shù)呢廓八,可見的幾點(diǎn)好處如下:

可緩存性(Cacheable)

重復(fù)的計(jì)算不需要多次計(jì)算,這就是可緩存性赵抢。


let addFive = memoize(x=>x+5)

addFive(1); 
addFive(1);
addFive(1); 
//真正的計(jì)算只會(huì)發(fā)生一次剧蹂。

memoize的實(shí)現(xiàn)很簡(jiǎn)單,使用一個(gè)對(duì)象來存儲(chǔ)計(jì)算過的值即可烦却。下面是一個(gè)簡(jiǎn)單的實(shí)現(xiàn)


const momize=(func)=>{
    //cache對(duì)象用于存儲(chǔ)計(jì)算過的值
    let cache={}
    
    return ()=>{
        let key = JSON.stringify(arguments)
        if(!cache[key]){
            cache[key] = func.apply(this,arguments)
        }
        
        return cache[key]
    }
}

可移植性(Portable)

純函數(shù)的依賴很明確宠叼,需要的數(shù)據(jù)都在參數(shù)中體現(xiàn)了。這樣做短绸,使應(yīng)用更加靈活车吹。因?yàn)橐磺械囊蕾嚩紖?shù)化了,當(dāng)依賴變化時(shí)醋闭,直接把新的依賴傳遞進(jìn)去就好了窄驹。

可測(cè)試性(Testable)

這也是可以預(yù)見的,相同的輸入具有相同的輸出证逻。意味著測(cè)試時(shí)我們只需要給函數(shù)一個(gè)輸入乐埠,然后斷言它的輸出即可。

引用透明(referential transparency)

函數(shù)的返回值只依賴于它的輸入,這就是引用透明性丈咐。很明顯瑞眼,純函數(shù)具有這個(gè)特性。這個(gè)特性可以幫助我們更好的分析我們的程序棵逊。

并行

純函數(shù)可以任意并行的運(yùn)行伤疙。因?yàn)榧兒瘮?shù)沒有副作用,不會(huì)和其它純函數(shù)進(jìn)入競(jìng)爭(zhēng)狀態(tài)辆影。也不需要訪問共享的內(nèi)存徒像。

柯里化

對(duì)于函數(shù)式編程來說,柯里化是一個(gè)不可或缺的工具蛙讥。它的概念很簡(jiǎn)單锯蛀,只傳遞給函數(shù)一部分參數(shù)來調(diào)用它,返回一個(gè)接受剩下參數(shù)的函數(shù)次慢。
一個(gè)被舉得最多的例子:


const addFunc =(a,b,c,d)=>{
    return a+b+c+d;
}

const add = curry(addFunc)

add(1)(2)(3)(4)   //10
add(1,2)(3,4)     //10
add(1,2,3,4)      //10

經(jīng)過柯里化旁涤,現(xiàn)在我們不需要再一次性的將所有參數(shù)傳入了。

代碼組合(compose)

之前我有一篇文章分析過redux的源碼迫像,其中有一個(gè)文件compose.js:


export default function compose(...funcs) {
  if (funcs.length === 0) {
    return arg => arg
  }

  if (funcs.length === 1) {
    return funcs[0]
  }

  return funcs.reduce((a, b) => (...args) => a(b(...args)))  
}

這就是組合函數(shù)劈愚,一個(gè)函數(shù)的返回將作為另一個(gè)函數(shù)的輸入。

PS:這個(gè)代碼是從左往右運(yùn)行的侵蒙,函數(shù)式推薦從右向左運(yùn)行造虎。據(jù)說這樣更加能夠反映數(shù)學(xué)上的含義。
通過組合纷闺,我們可以像搭積木一樣把簡(jiǎn)單的功能拼湊成復(fù)雜的功能。

pointfree

這是一種風(fēng)格份蝴,指的是數(shù)據(jù)無關(guān)犁功,就像上面的compose,舉個(gè)例子:


//非pointfree 風(fēng)格
let upperReplace=(arg)=>{
    return arg.toUpperCase().replace(/\s+/ig/,'_')
}

//pointfree風(fēng)格
let upperReplace = compose(replace(/\s+/ig/,'_'),toUpperCase)

非常明顯婚夫,非pointfree模式提到了數(shù)據(jù)arg浸卦,而pointfree沒有“覆冢可以看出pointfree還能幫我們減少不必要的命名限嫌,我相信你們也和我一樣覺得命名是一件頭疼的事。

debug

使用組合有時(shí)容易出錯(cuò)时捌,比如參數(shù)個(gè)數(shù)對(duì)應(yīng)不上之類的怒医。對(duì)于組合有一種比較實(shí)用但不純的方法來追蹤代碼的執(zhí)行情況。


let trace = curry((tag,x)=>{
    console.log(tag,x);
    return x;
})

//將trace放在合適的地方奢讨,就可以看到該處的日志稚叹,從而糾錯(cuò)
let test = compose(otherOper,trace("after toUpper"),toUpper,firstEle,reverse)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子扒袖,更是在濱河造成了極大的恐慌塞茅,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件季率,死亡現(xiàn)場(chǎng)離奇詭異野瘦,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)飒泻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門缅刽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蠢络,你說我怎么就攤上這事衰猛。” “怎么了刹孔?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵啡省,是天一觀的道長。 經(jīng)常有香客問我髓霞,道長卦睹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任方库,我火速辦了婚禮结序,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘纵潦。我一直安慰自己徐鹤,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布邀层。 她就那樣靜靜地躺著返敬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪寥院。 梳的紋絲不亂的頭發(fā)上劲赠,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音秸谢,去河邊找鬼凛澎。 笑死,一個(gè)胖子當(dāng)著我的面吹牛估蹄,可吹牛的內(nèi)容都是我干的塑煎。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼元媚,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼轧叽!你這毒婦竟也來了苗沧?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤炭晒,失蹤者是張志新(化名)和其女友劉穎待逞,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體网严,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡识樱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了震束。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片怜庸。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖垢村,靈堂內(nèi)的尸體忽然破棺而出割疾,到底是詐尸還是另有隱情,我是刑警寧澤嘉栓,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布宏榕,位于F島的核電站,受9級(jí)特大地震影響侵佃,放射性物質(zhì)發(fā)生泄漏麻昼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一馋辈、第九天 我趴在偏房一處隱蔽的房頂上張望抚芦。 院中可真熱鬧,春花似錦迈螟、人聲如沸叉抡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽卜壕。三九已至,卻和暖如春烙常,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鹤盒。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來泰國打工蚕脏, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人侦锯。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓驼鞭,卻偏偏與公主長得像,于是被迫代替她去往敵國和親尺碰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子挣棕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

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