函數(shù)式編程

主要的編程范式有三種:命令式編程钙姊,聲明式編程和函數(shù)式編程。

命令式編程:

命令式編程的主要思想是關注計算機執(zhí)行的步驟,即一步一步告訴計算機先做什么再做什么边灭。

比如:如果你想在一個數(shù)字集合 collection(變量名) 中篩選大于 5 的數(shù)字,你需要這樣告訴計算機:

第一步健盒,創(chuàng)建一個存儲結果的集合變量 results绒瘦;

第二步,遍歷這個數(shù)字集合 collection扣癣;

第三步:一個一個地判斷每個數(shù)字是不是大于 5惰帽,如果是就將這個數(shù)字添加到結果集合變量 results 中。

很明顯父虑,這個樣子的代碼是很常見的一種该酗,不管你用的是 C, C++ 還是 C#, Java, Javascript, BASIC, Python, Ruby?等等,你都可以以這個方式寫士嚎。


聲明式編程:

聲明式編程是以數(shù)據(jù)結構的形式來表達程序執(zhí)行的邏輯呜魄。它的主要思想是告訴計算機應該做什么,但不指定具體要怎么做莱衩。

SQL 語句就是最明顯的一種聲明式編程的例子爵嗅,例如:

SELECT*FROM collection WHERE num>5

除了 SQL,網(wǎng)頁編程中用到的 HTML 和 CSS 也都屬于聲明式編程笨蚁。

通過觀察聲明式編程的代碼我們可以發(fā)現(xiàn)它有一個特點是它不需要創(chuàng)建變量用來存儲數(shù)據(jù)睹晒。


函數(shù)式編程:

“函數(shù)式編程”, 又稱泛函編程, 是一種”編程范式”(programming paradigm)趟庄,也就是如何編寫程序的方法論,和指令式編程相比伪很,函數(shù)式編程的思維方式更加注重函數(shù)的計算岔激。函數(shù)式編程和聲明式編程是有所關聯(lián)的,因為他們思想是一致的:即只關注做什么而不是怎么做是掰。但函數(shù)式編程不僅僅局限于聲明式編程虑鼎。它的主要思想是把問題的解決方案寫成一系列嵌套的函數(shù)調用。

函數(shù)式編程最重要的特點是“函數(shù)第一位”键痛,即函數(shù)可以出現(xiàn)在任何地方炫彩,比如你可以把函數(shù)作為參數(shù)傳遞給另一個函數(shù),不僅如此你還可以將函數(shù)作為返回值絮短。大部分常見的編程語言一半都已經提供了對這種編程方式的支持江兢,比如 JavaScript,再有 C# 中的 LINQ 和 Java 中的 Lambda 和閉包的概念丁频。

使用指令式編程時杉允,當情況變得更加復雜,表達式的寫法會遇到幾個問題:表意不明顯席里,逐漸變得難以維護復用性差叔磷,會產生更多的代碼量會產生很多中間變量。這個時候使用函數(shù)式編程的優(yōu)勢就提現(xiàn)出來了:

函數(shù)式編程的優(yōu)點

1. 代碼簡潔奖磁,開發(fā)快速

函數(shù)式編程大量使用函數(shù)改基,減少了代碼的重復,因此程序比較短咖为,開發(fā)速度較快秕狰。

// 數(shù)組中每個單詞,首字母大寫

// 一般寫法

const arr = ['apple','pen','apple-pen'];

for(const i in arr){

const c = arr[i][0];

arr[i] = c.toUpperCase() + arr[i].slice(1);

}

console.log(arr);

// 函數(shù)式寫法一

function upperFirst(word){

returnword[0].toUpperCase() + word.slice(1);

}

function wordToUpperCase(arr){

returnarr.map(upperFirst);

}

console.log(wordToUpperCase(['apple','pen','apple-pen']));

// 函數(shù)式寫法二

console.log(arr.map(['apple','pen','apple-pen'], word => word[0].toUpperCase() + word.slice(1)));

2. 接近自然語言躁染,易于理解

函數(shù)式編程的自由度很高鸣哀,可以寫出很接近自然語言的代碼。

將表達式(1 + 2) * 3 - 4吞彤,寫成函數(shù)式語言:subtract(multiply(add(1,2), 3), 4)

對它進行變形我衬,不難得到另一種寫法:add(1,2).multiply(3).subtract(4)

這基本就是自然語言的表達了。再看下面的代碼备畦,大家應該一眼就能明白它的意思吧:

merge([1,2],[3,4]).sort().search("2")

因此低飒,函數(shù)式編程的代碼更容易理解。

3. 更方便的代碼管理

函數(shù)式編程不依賴懂盐、也不會改變外界的狀態(tài)褥赊,只要給定輸入?yún)?shù),返回的結果必定相同莉恼。因此拌喉,每一個函數(shù)都可以被看做獨立單元速那,很有利于進行單元測試(unit testing)和除錯(debugging),以及模塊化組合尿背。


函數(shù)編程的一些基本特點包括:

1. 函數(shù)是”第一等公民”:

????函數(shù)與其他數(shù)據(jù)類型一樣端仰,處于平等地位,可以賦值給其他變量田藐,也可以作為參數(shù)荔烧,傳入另一個函數(shù),或者作為別的函數(shù)的返回值汽久。

2. 高階函數(shù)(Higher Order Function):

? ? 將函數(shù)作為參數(shù)鹤竭,或者是可以將函數(shù)作為返回值的函數(shù)。比如我們平常用到的回調函數(shù).

3. 函數(shù)柯里化(Currying):

? ??把接受多個參數(shù)的函數(shù)變換成接受一個單一參數(shù)(最初函數(shù)的第一個參數(shù))的函數(shù)景醇,并且返回接受余下的參數(shù)且返回結果的新函數(shù)臀稚。

其過程就是消化一個參數(shù),然后生成一個新的函數(shù)三痰,剩余的參數(shù)作為新函數(shù)的參數(shù)吧寺。

// 柯里化之前

function?add(x, y) {

????return?x + y;

}

add(1, 2)?// 3

// 柯里化之后

function?addX(y) {

????return?function?(x) {

????????return?x + y;

????};

}

addX(2)(1)?// 3

4. 懶惰計算(lazy evaluation):

? ??在惰性計算中,表達式不是在綁定到變量時立即計算散劫,而是在求值程序需要產生表達式的值時進行計算稚机。

5. 引用透明性:

指的是函數(shù)的運行不依賴于外部變量或"狀態(tài)",只依賴于輸入的參數(shù)舷丹,任何時候只要參數(shù)相同抒钱,引用函數(shù)所得到的返回值總是相同的。

6. 沒有副作用:

? ??意味著函數(shù)要保持獨立颜凯,所有功能就是返回一個新的值,沒有其他行為仗扬,尤其是不得修改外部變量的值症概。

7. 純函數(shù):

? ??- 其結果只能從它的參數(shù)的值來計算?

????- 不能依賴于能被外部操作改變的數(shù)據(jù)?

????- 不能改變外部狀態(tài)


函數(shù)式編程思維在我們工作中的體現(xiàn)

? ? 1.map/reduce/filter方法

? ? 傳入一個函數(shù)作為參數(shù),返回一個新的數(shù)組早芭,不對原來的數(shù)組進行修改彼城,不使用中間變量,沒有副作用退个。

? ? 2.閉包

????閉包的主要用途就是可以定義一些作用域局限的持久化變量募壕,這些變量可以用來做緩存或者計算的中間量等等。

????下面的例子是一個簡單的緩存工具的實現(xiàn)语盈,匿名函數(shù)創(chuàng)造了一個閉包舱馅,使得?store?對象 ,一直可以被引用刀荒,不會被回收代嗤。

// 簡單的緩存工具

const cache = (function() {

????const store = {};

????return {

????????get(key) {

????????????return store[key];

????????},

????????set(key, val) {

????????????store[key] = val;

????????}

????}

}());

cache.set('a', 1);

cache.get('a'); // 1

????3.鏈式優(yōu)化

? ? 比如回調函數(shù)和promise函數(shù)

// 優(yōu)化寫法 (loadsh 的鏈式寫法)

constutils = {

? chain(a) {

this._temp = a;

returnthis;

? },

? sum(b) {

this._temp += b;

returnthis;

? },

? sub(b) {

this._temp -= b;

returnthis;

? },

? value() {

const_temp =this._temp;

this._temp =undefined;

return_temp;

? }

};

console.log(utils.chain(1).sum(2).sum(3).sub(4).value());

4.連續(xù)箭頭函數(shù)

function add(a) {

? ? return function(b) {

? ? ? ? return a + b

? ? }

}

var add3 = add(3)

add3(4) === 3 + 4 //true

add 函數(shù) 在 es6 里的寫法等價為

let add = a => b => a + b

add(3)(4)


參考文章:

https://github.com/EasyKotlin/chapter8_fp

http://taobaofed.org/blog/2017/03/16/javascript-functional-programing/

https://www.cnblogs.com/sirkevin/p/8283110.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末棘钞,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子干毅,更是在濱河造成了極大的恐慌宜猜,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件硝逢,死亡現(xiàn)場離奇詭異姨拥,居然都是意外死亡,警方通過查閱死者的電腦和手機渠鸽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門垫毙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人拱绑,你說我怎么就攤上這事综芥。” “怎么了猎拨?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵膀藐,是天一觀的道長。 經常有香客問我红省,道長额各,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任吧恃,我火速辦了婚禮虾啦,結果婚禮上,老公的妹妹穿的比我還像新娘痕寓。我一直安慰自己傲醉,他們只是感情好,可當我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布呻率。 她就那樣靜靜地躺著硬毕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪礼仗。 梳的紋絲不亂的頭發(fā)上吐咳,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天,我揣著相機與錄音元践,去河邊找鬼韭脊。 笑死,一個胖子當著我的面吹牛单旁,可吹牛的內容都是我干的沪羔。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼慎恒,長吁一口氣:“原來是場噩夢啊……” “哼任内!你這毒婦竟也來了撵渡?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤死嗦,失蹤者是張志新(化名)和其女友劉穎趋距,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體越除,經...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡节腐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了摘盆。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片翼雀。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖孩擂,靈堂內的尸體忽然破棺而出狼渊,到底是詐尸還是另有隱情,我是刑警寧澤类垦,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布狈邑,位于F島的核電站,受9級特大地震影響蚤认,放射性物質發(fā)生泄漏米苹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一砰琢、第九天 我趴在偏房一處隱蔽的房頂上張望蘸嘶。 院中可真熱鬧,春花似錦陪汽、人聲如沸训唱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽雪情。三九已至,卻和暖如春你辣,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背尘执。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工舍哄, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人誊锭。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓表悬,卻偏偏與公主長得像,于是被迫代替她去往敵國和親丧靡。 傳聞我的和親對象是個殘疾皇子蟆沫,可洞房花燭夜當晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內容