函數(shù)式編程思維筆記

一汽纠、核心思想

函數(shù)式編程語言,讓我們用高階抽象取代基本的控制結(jié)構(gòu)丧叽。

面向?qū)ο缶幊掏ㄟ^封裝不確定因素使代碼被人理解;函數(shù)式編程通過盡量減少不確定因素使代碼被人理解骚灸。 ---- Micheal Feathers

面向?qū)ο缶幊蹋褐赜玫膯卧穷惡皖愔g的溝通消息(方法)。OOP提倡開發(fā)者針對具體問題建立專門的數(shù)據(jù)結(jié)構(gòu)驴一,以專門的操作(方法)附在數(shù)據(jù)結(jié)構(gòu)上休雌。

函數(shù)式編程:提倡在有限幾種關(guān)鍵數(shù)據(jù)結(jié)構(gòu)(List,Map肝断,set)上針對這些數(shù)據(jù)結(jié)構(gòu)進(jìn)行高度優(yōu)化的操作(方法)杈曲,以此構(gòu)成基本運(yùn)轉(zhuǎn)機(jī)制。開發(fā)者根據(jù)具體的用途插入自己的數(shù)據(jù)結(jié)構(gòu)和高階函數(shù)去調(diào)整整體機(jī)制的運(yùn)轉(zhuǎn)方式胸懈。

二担扑、思維轉(zhuǎn)變

學(xué)習(xí)新的語言,把熟悉的概念用新的語法表達(dá)出來趣钱。
學(xué)習(xí)新的范式涌献,為熟悉的問題找到新的解答方法。

函數(shù)式編程首有,需要站在更高的抽象層次上工作洁奈。

命令式編程:按照程序是一系列狀態(tài)改變的命令來建模的一種編程風(fēng)格。例如 for 循環(huán) 绞灼,先確認(rèn)初始狀態(tài)利术,每次都執(zhí)行每次迭代循環(huán)體中的一系列命令。命令式編程鼓勵將操作安排在循環(huán)內(nèi)部進(jìn)行低矮。
函數(shù)式編程:將程序描述為表達(dá)式和變換印叁,以數(shù)學(xué)的方式建立模型,盡量避免可變的狀態(tài)军掂。

高階函數(shù)消除了摩擦

函數(shù)式的基本構(gòu)造單元

  • 篩選 (filter)
    需要根據(jù)篩選條件產(chǎn)生一個子集合 使用filter
  • 映射(map)
    對原集合中的每一個元素執(zhí)行給定的函數(shù),從而變成一個新的集合.
  • 折疊和化約(fold,reduce)
    用一個累積量來"收集"集合元素.比如fold的含義為用一個二元函數(shù)或者云算符結(jié)合列表的首元素和累積量的初始值,重復(fù)上一步直到列表耗盡,此時累積量的取值為折疊運(yùn)算的結(jié)果.
    需要把一個集合分成一小塊一小塊的來處理,使用fold或reduce

三轮蜕、權(quán)責(zé)讓渡

抽象的目的總是一樣的:讓開發(fā)者從繁瑣的細(xì)節(jié)中解脫出來,去解答問題中非重復(fù)性的那些部分蝗锥。

1.迭代讓位高階函數(shù)

2.閉包

閉包:是一種奇特的函數(shù)跃洛,他把需要引用的內(nèi)部變量都放在上下文里“包”起來了。換句話說终议,對于所需的內(nèi)部變量可以讓調(diào)用者靈活創(chuàng)建汇竭。一般閉包包括兩個步驟,創(chuàng)建綁定和執(zhí)行穴张。
Groovy中閉包示例:

class Employee {
    def name, salary
}
//創(chuàng)建閉包
def paidMore(amount) {
    return { Employee e -> e.salary > amount }
}
//綁定閉包
isPaidMore=paidMore(10000)
//執(zhí)行閉包
def lily = new Employee("Lily", 15000)
println(isPaidMore(lily))

//綁定閉包
isPaidMore2=paidMore(20000)
//執(zhí)行閉包
def lucy = new Employee("Lucy", 20000)
println(isPaidMore2(lucy))

這里面 paidMore就是一個閉包细燎,isPaidMore,isPaidMore2是閉包的實(shí)例皂甘。
每個閉包實(shí)例中保有自己的一份變量取值玻驻,包括私有變量也是如此。

閉包經(jīng)常被函數(shù)式語言和框架當(dāng)做一種異地執(zhí)行的機(jī)制,用來傳遞待執(zhí)行的變換代碼偿枕,例如map之類的高階函數(shù)

  • 科里化和函數(shù)的部分施用

科里化:如果你固定某些參數(shù)璧瞬,你將得到接受余下參數(shù)的一個函數(shù)户辫。對于一個兩個可變量的函數(shù)xy,如果固定y=2嗤锉,將得到有一個可變量的函數(shù)2x渔欢。一般情況f(x,y,z)=>f(x)(y)(z) 把函數(shù)多個參數(shù)變成一連串單個參數(shù)的變換。

部分施用:提前帶入一部分參數(shù)值档冬,使得多個參數(shù)的函數(shù)得以省略部分參數(shù)膘茎,從而得到單個參數(shù)的函數(shù)桃纯。先求解一部分參數(shù)酷誓,返回由剩下參數(shù)構(gòu)成簽名的函數(shù)。一般情況态坦,如果在f(x,y,z)上部分施用一個參數(shù)盐数,將得剩余兩個參數(shù)的函數(shù)f(y,z)。

image.png

3.科里化和部分施用一般用途

1.函數(shù)工廠
在傳統(tǒng)面向?qū)ο?/p>

image.png

2.模板方法模式
GoF的模板方法(Template Method)的用意是在固定的算法框架內(nèi)部安排一些抽象方法伞梯,為后續(xù)具體實(shí)現(xiàn)保留一部分靈活行玫氢。部分施用先固定一部分參數(shù)(注入當(dāng)前已確定的行為),留下未確認(rèn)的參數(shù)給具體實(shí)現(xiàn)去發(fā)揮谜诫,思路和模板方法如出一轍漾峡。

3.隱含參數(shù)
當(dāng)我們需要頻繁調(diào)用一個函數(shù),而每次參數(shù)值都差不多時喻旷,使用科里化來設(shè)置隱含參數(shù)生逸。【把參數(shù)值固定】

4.遞歸

遞歸:“以一種自相似的方式來重復(fù)事物的過程”且预。
是運(yùn)行時托付細(xì)節(jié)的一個例子槽袄,而且和函數(shù)式編程有著緊密聯(lián)系。

四. 函數(shù)的兩種常見特性

函數(shù)式編程的構(gòu)造目的:從頻繁出現(xiàn)的場景中 消滅掉煩人的細(xì)節(jié)

1.記憶

指的是在函數(shù)級別上對多次需要使用的值進(jìn)行緩存的策略.

緩存兩種用法:
  • 內(nèi)部緩存
  • 外部緩存
緩存的兩種實(shí)現(xiàn)方式
  • 手工實(shí)現(xiàn)狀態(tài)管理
  • 自動記憶機(jī)制

2.引入記憶

記憶函數(shù),使用了所謂"元函數(shù)"技法(操作的對象是函數(shù)本身,而非函數(shù)結(jié)果)

3.緩求值

緩求值的集合不會預(yù)先算好所有的元素,而是在需要用到的時候才落實(shí)下來.
有3大好處:

  • 昂貴的運(yùn)算只有到了絕對必要時候才執(zhí)行
  • 可以建立無限大集合,只要一有請求,就一直送出元素
  • 按緩求值的方式來使用映射,過濾等函數(shù)可以產(chǎn)生高效代碼

4.構(gòu)造緩求值列表

對于嚴(yán)格求值的語言,如果使用閉包遞歸的將一個嚴(yán)格求值列表層層包裹起來,就可以將之變成緩求值列表.現(xiàn)實(shí)中會避免施用遞歸.

五.模式與重用

大多數(shù)現(xiàn)代語言是多范式,支持對象,函數(shù)式,元對象,以及其他多樣化范式.
在不同的范式中表現(xiàn)出來的設(shè)計(jì)模式,可能呈現(xiàn)截然不同的外在形象.這是因?yàn)楹瘮?shù)式世界用來搭建程序的材料不一樣,所以解決問題的手段也不同.GoF的模式有一部分傳統(tǒng)模式失去了存在的意義,還有一部分,他們要解決的問題還存在,只是解決手段不一樣.

傳統(tǒng)的設(shè)計(jì)模式在函數(shù)式編程世界中大致有3中歸宿:

  • 模式已經(jīng)被吸收成語言的一部分
  • 模式中描述解決的辦法依然還成立,具體的實(shí)現(xiàn)細(xì)節(jié)有變化
  • 由于新語言或者范式獲得了原本沒有的能力,有了新的解決方案.(例如元編程)

1.函數(shù)級別的重用

復(fù)用(composition),作為一種重用機(jī)制,在函數(shù)式語言中主要表現(xiàn)為:通過參數(shù)傳遞函數(shù).與面向?qū)ο笳Z言相比,函數(shù)式語言重用發(fā)生在粗粒度的級別上,著眼提取共通的運(yùn)行機(jī)制,并參數(shù)化調(diào)整其行為.

函數(shù)式的重用機(jī)制建立在列表的概念,以及可以連同上下文一期傳遞的代碼塊的概念之上.

函數(shù)式語言作為第一等成分的函數(shù),可以充當(dāng)參數(shù)和返回值.

- 函數(shù)式模板模式(Template Method)

- Strategy模式

- Flyweight 模式和記憶

- 單例模式

- Factory模式和科里化

2.結(jié)構(gòu)化重用和函數(shù)式重用的對比

1.以結(jié)構(gòu)為載體的代碼重用
如果面向?qū)ο蟮拇a值得重用,我們一般會把他提取到另一個類中,然后通過繼承來訪問它.

六.現(xiàn)實(shí)應(yīng)用

  • 函數(shù)式接口
    含有單一方法的接口,稱為函數(shù)式接口SAM(single Abstract Method),runnable 和callable接口就是有代表性的例子.在java中允許通過lambda 和SAM攜手.
  • Optional類型
    Optional 是一種結(jié)構(gòu),防止返回結(jié)果出現(xiàn)null
  • Stream

函數(shù)式的基礎(chǔ)設(shè)施

在數(shù)據(jù)庫,軟件架構(gòu)上函數(shù)是思維的作用?

1.架構(gòu)

函數(shù)式的架構(gòu)從根本上貫徹"值不可變"的思路,最大的發(fā)揮其優(yōu)點(diǎn).學(xué)會從值不變的角度去思考,是我們掌握函數(shù)式思維的一條重要門徑.

- CQRS

傳統(tǒng)應(yīng)用 程序架構(gòu)把讀寫數(shù)據(jù)交織一起.例如

壞處:模型需要負(fù)責(zé)處理業(yè)務(wù)規(guī)則和驗(yàn)證的工作,一般模型對象還要在內(nèi)部或通過另外的邏輯層來協(xié)調(diào)持久化事項(xiàng).開發(fā)者需要兼顧讀寫兩方面潛在的影響,增加復(fù)雜性.

CQRS 通過分離架構(gòu)中負(fù)責(zé)讀取的部分和負(fù)責(zé)命令的部分,部分的簡化了程序的架構(gòu).

架構(gòu)永遠(yuǎn)是取舍的結(jié)果,CQRS簡化了一些方面,同時又復(fù)雜話了另一些方面.例如對于集中式數(shù)據(jù)庫來說,事務(wù)處理并不難.可是在CQRS架構(gòu)下,我們可能需要用最終一致性模型來取代事務(wù)性的模型.

最終一致性:是分布式中的一種模型,不對模型的變更操作施加硬性的時間限制,而只保證,當(dāng)更新發(fā)生后,模型最終回復(fù)到一致的狀態(tài).

2.Web框架

web領(lǐng)域與函數(shù)式編程簡直是天作之合.這些web框架大多具備以下共同特性:

  • 路由框架
    從應(yīng)用主體中剝離路由的相關(guān)細(xì)節(jié),將之交托專門的路由功能庫.
  • 以函數(shù)作為路由的目標(biāo)
    把路由理解成一個接收request,返回response的函數(shù).
  • 領(lǐng)域?qū)S妙A(yù)言(DSL)
    MartinFowler 將DSL定義為表達(dá)能力有限,專門針對一個狹窄問題領(lǐng)域的計(jì)算機(jī)編程語言.函數(shù)式預(yù)言偏好描述性的代碼風(fēng)格這一點(diǎn)恰好也常常是DSL的目的.
  • 與構(gòu)建工具緊密集成
    總體來說,不可變的值編程,會降低測試的負(fù)擔(dān),因?yàn)樾枰ㄟ^測試來驗(yàn)證的狀態(tài)變化少了.

七.多語言與多范式

現(xiàn)代編程語言常常是多范式的,支持多種多樣的編程范式,如面向?qū)ο?元編程,函數(shù)式,過程式等等.

正交 在數(shù)學(xué)里吧兩個相互垂直的向量稱作正交,也就是說這兩個向量不相關(guān)(不會相交).在計(jì)算機(jī)科學(xué)里,把兩個組件如果沒有相互沒有任何影響(或副作用),就可以稱作是正交的.例如在groove,kotlin 中使用元編程并不妨礙我們使用函數(shù)式編程的構(gòu)造,反之亦然.

2.多范式預(yù)言的后顧之憂

由于預(yù)言支持各式各樣的抽象和概念,由不同的開發(fā)群體制作出來的庫也會呈現(xiàn)明顯的差異.不同范式的思路是不一樣的.可以運(yùn)用"消費(fèi)者驅(qū)動的契約",(以測試的形式)在不同團(tuán)隊(duì)之間簡歷可執(zhí)行的契約.

消費(fèi)者驅(qū)動的契約:
一項(xiàng)集成工作的實(shí)施方與各組件供應(yīng)方共同商定的一組測試.集成方"同一",如果一方需要打破前設(shè)置條件,必須著急所受歐影響的當(dāng)事方,議定一組新的測試.

3.上下文型抽象與復(fù)合型抽象對比

復(fù)合是函數(shù)是編程領(lǐng)域奉為圭臬的設(shè)計(jì)原則.
上下文型是 基于插件的架構(gòu)使用的設(shè)計(jì)原則.

4.函數(shù)是金字塔

進(jìn)行語言的選型

語言的選型.png

不應(yīng)該從靜態(tài)類型中求索抵御錯誤的能力,從根本上擁抱函數(shù)式的概念才是正確方向.假如包括數(shù)據(jù)訪問,集成等重要職責(zé)在內(nèi)的核心api,都能以值不變性為前提來設(shè)計(jì)的話,那么所有的代碼都對大幅度地簡化.當(dāng)然在這思路下,數(shù)據(jù)庫和其他基礎(chǔ)設(shè)施的構(gòu)建方式也需要隨之放生變化.

在函數(shù)式內(nèi)核之上,用命令式語言編寫系統(tǒng)中對開發(fā)效率要求較高的部分,例如工作流,業(yè)務(wù)規(guī)則,用戶界面.最上層和原來模型一樣是 DSL層,DSL會貫穿系統(tǒng)的所有層次,一致深入到最底層.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末锋谐,一起剝皮案震驚了整個濱河市遍尺,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌涮拗,老刑警劉巖乾戏,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異三热,居然都是意外死亡歧蕉,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進(jìn)店門康铭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來惯退,“玉大人,你說我怎么就攤上這事从藤〈吖颍” “怎么了锁蠕?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長懊蒸。 經(jīng)常有香客問我荣倾,道長,這世上最難降的妖魔是什么骑丸? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任舌仍,我火速辦了婚禮,結(jié)果婚禮上通危,老公的妹妹穿的比我還像新娘铸豁。我一直安慰自己,他們只是感情好菊碟,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布节芥。 她就那樣靜靜地躺著,像睡著了一般逆害。 火紅的嫁衣襯著肌膚如雪头镊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天魄幕,我揣著相機(jī)與錄音相艇,去河邊找鬼。 笑死纯陨,一個胖子當(dāng)著我的面吹牛坛芽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播队丝,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼靡馁,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了机久?” 一聲冷哼從身側(cè)響起臭墨,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎膘盖,沒想到半個月后胧弛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡侠畔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年结缚,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片软棺。...
    茶點(diǎn)故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡红竭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情茵宪,我是刑警寧澤最冰,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站稀火,受9級特大地震影響暖哨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜凰狞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一篇裁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧赡若,春花似錦达布、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伐庭。三九已至粉渠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間圾另,已是汗流浹背霸株。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留集乔,地道東北人去件。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像扰路,于是被迫代替她去往敵國和親尤溜。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評論 2 348

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