純函數(shù)
一個函數(shù)在程序執(zhí)行的過程中除了根據(jù)輸入?yún)?shù)給出運算結(jié)果之外沒有其他的副作用影響遗座,我們可以把這類函數(shù)稱為“純函數(shù)”榴捡。純函數(shù)由于不依賴外部變量,使得給定函數(shù)輸入其返回結(jié)果永遠(yuǎn)不變衡载,比如整數(shù)的加法函數(shù)允乐,它接收兩個整數(shù)值并返回一個整數(shù)值,對于給定的兩個整數(shù)值茫因,它的返回值永遠(yuǎn)是相同的整數(shù)值蚪拦。
副作用
相對于非純函數(shù),它們帶有副作用冻押,這使得函數(shù)不僅簡單返回一個值驰贷,還做了其他事情:
- 修改了一個變量
- 直接修改了數(shù)據(jù)結(jié)構(gòu)
- 設(shè)置了一個對象的成員
- 拋出一個異常或以一個錯誤終止
- 打印到終端或讀取用戶的輸入
- 讀取或?qū)懭胍粋€文件
- 在屏幕上繪畫
像是執(zhí)行IO洛巢、處理錯誤括袒、修改數(shù)據(jù)都屬于副作用,這些副作用可能導(dǎo)致我們編寫的程序難以測試稿茉,進而容易產(chǎn)生bug箱熬。遵循函數(shù)式編程規(guī)范可以使編程更加模塊化,由于純函數(shù)模塊化的特性狈邑,使得程序容易被測試城须、復(fù)用、并行化米苹、泛化以及推導(dǎo)糕伐,這也減少了產(chǎn)生bug的可能。
純函數(shù)的使用將數(shù)據(jù)的創(chuàng)建過程和處理過程分離蘸嘶,通過把副作用推導(dǎo)程序的外層良瞧,來轉(zhuǎn)換任何帶有副作用的函數(shù)陪汽。對于函數(shù)式程序員而言,程序的實現(xiàn)應(yīng)該有一個純的內(nèi)核和一層很薄的外圍來處理副作用褥蚯。
引用透明
引用透明(referential transparency)的概念對純函數(shù)進行形式化挚冤,符合引用透明的表達式都可以由它的結(jié)果所取代,而不改變該程序的含義赞庶。當(dāng)調(diào)用一個函數(shù)時所傳入的參數(shù)是引用透明的训挡,冰鞋函數(shù)調(diào)用也是引用透明的,那么這個函數(shù)式一個純函數(shù)歧强。當(dāng)傳入函數(shù)的參數(shù)也是一個純函數(shù)時澜薄,使得高階函數(shù)的組合也是引用透明的,這有利于構(gòu)建更加復(fù)雜的邏輯摊册,而本身程序的計算結(jié)果是可以進行推斷的肤京,不用擔(dān)心環(huán)境對程序的影響。
對于程序p茅特,如果它包含的表達式e滿足引用透明忘分,所有的e都可以替換為它的運算結(jié)果而不會改變程序p的含義。假設(shè)存在一個函數(shù)f白修,若變大時f(x)對所有引用透明的表達式x也是引用透明的饭庞,那么這個f是一個純函數(shù)。
替代模型
引用透明要求函數(shù)不論進行了任何操作都可以用它的返回值來代替熬荆。這種限制使得推導(dǎo)一個程序的求值變得簡單而自然舟山,稱之為替代模型(substitution model)。如果表達式是引用透明的卤恳,可以想象計算過程就像在解代數(shù)方程累盗。展開表達式的每一部分,使用指示對象替代變量突琳,然后歸約到最簡單的形式若债。在這一過程中,每項都被等價值所替代拆融,計算的過程就是一個又一個等價值所替代的過程蠢琳。換句話說,引用透明使得程序具備了等式推理的能力镜豹。
替代模型更容易推理傲须,因為對運算的影響純粹是局部的(只對那些賦值表達式產(chǎn)生影響),不需要先在內(nèi)心模擬一系列狀態(tài)的更新才理解這一段代碼趟脂。只需要理解局部的推理泰讽,不必費心地去跟蹤函數(shù)執(zhí)行前后的狀態(tài)變化,只用簡單看一下函數(shù)的定義,把它替換成一個參數(shù)已卸。
小結(jié)
這一小節(jié)佛玄,我們了解了純函數(shù)的一些基本概念和其帶來的好處。我們知道累澡,純函數(shù)時模塊化的梦抢、可組合的,因為它從“對結(jié)果做什么”和“如果獲取輸入”中分離了計算本身的邏輯愧哟,就像一個黑盒子奥吩。對輸入的獲取只有一種方式:通過參數(shù)傳給函數(shù)。輸出也只是簡單地將計算結(jié)果返回翅雏。把這些關(guān)注點分離開,計算也更容易被復(fù)用人芽。我們可以復(fù)用這些邏輯望几,而不必?fù)?dān)心輸入或輸出對整個上下文引起的副作用。
轉(zhuǎn)載請注明作者Jason Ding及其出處
jasonding.top
Github博客主頁(http://blog.jasonding.top/)
CSDN博客(http://blog.csdn.net/jasonding1354)
簡書主頁(http://www.reibang.com/users/2bd9b48f6ea8/latest_articles)
Google搜索jasonding1354進入我的博客主頁