函數(shù)式編程

最初給自己定的計(jì)劃是一個(gè)月更新一篇博客泡态,但是執(zhí)行下來(lái)才發(fā)現(xiàn)自己還是太 naive,由于進(jìn)入了新的項(xiàng)目迂卢,所以現(xiàn)在每天都是工作24小時(shí)的狀態(tài)??某弦。。而克。靶壮。但是人總是要學(xué)習(xí)的,不然和咸魚(yú)有什么區(qū)別员萍,所以還是咬咬牙抽出自己為數(shù)不多的個(gè)人時(shí)間來(lái)接觸新的東西腾降。

函數(shù)式編程思想已經(jīng)存在幾十年了,算不上新的技術(shù)充活,但是在命令式編程大行其道的今天,了解不同的編程思想還是有助于開(kāi)闊自己的視野蜡娶,也能夠吸收其中的精華來(lái)讓代碼寫(xiě)得更好混卵。

初次接觸函數(shù)式編程的小伙伴可能會(huì)發(fā)出以下素質(zhì)三連:

啥函數(shù)啊窖张?我不正在用函數(shù)編程嗎幕随?大佬你到底在說(shuō)些啥啊宿接?

emmmmm赘淮,函數(shù)式編程的名字確實(shí)很容易招致誤解,但絕對(duì)不是寫(xiě)幾個(gè)函數(shù)運(yùn)行下就是函數(shù)式編程了??睦霎。函數(shù)式編程作為一種編程范式有著它自己獨(dú)特的設(shè)計(jì)理念和風(fēng)格梢卸,想要徹底講清楚可能需要幾本書(shū)的篇幅了。所以本文會(huì)著重介紹函數(shù)式編程的核心特性副女,幫助大家對(duì)函數(shù)式編程有一個(gè)大體的認(rèn)識(shí)蛤高。

朝花夕拾

時(shí)間要追溯到20世紀(jì)30年代,普林斯頓大學(xué)的數(shù)學(xué)家阿隆左·丘奇(Alonzo Church)正在進(jìn)行"可計(jì)算問(wèn)題"的研究:你怎樣判斷一個(gè)數(shù)學(xué)問(wèn)題是可以被計(jì)算的碑幅?證明和推導(dǎo)的過(guò)程是否可以自動(dòng)化戴陡?阿隆左·丘奇為此發(fā)明了 lambda 演算(相關(guān)科普可以參考這篇文章或者它的譯文):

lambda 演算由函數(shù)構(gòu)成,函數(shù)可以作為另外一個(gè)函數(shù)的輸入或輸出沟涨,一系列的函數(shù)調(diào)用最終會(huì)形成一個(gè)表達(dá)式鏈恤批,這個(gè)表達(dá)式鏈最終可以求得一個(gè)值,通過(guò)這個(gè)過(guò)程便能夠?qū)?wèn)題進(jìn)行推導(dǎo)演算裹赴。

"可計(jì)算問(wèn)題"是當(dāng)時(shí)數(shù)學(xué)領(lǐng)域的思潮喜庞,除了阿隆左·丘奇诀浪,還有很多優(yōu)秀的數(shù)學(xué)家對(duì)此感興趣,其中就包括阿蘭·圖靈(Alan Turing)赋荆。他提出了另一種模型來(lái)解決"可計(jì)算問(wèn)題"笋妥,也就是圖靈機(jī):

圖靈的基本思想是用機(jī)器來(lái)模擬人們用紙筆進(jìn)行數(shù)學(xué)運(yùn)算的過(guò)程,該機(jī)器由以下幾個(gè)部分組成:

  • 一條無(wú)限長(zhǎng)的紙帶 TAPE窄潭。紙帶被劃分為一個(gè)接一個(gè)的小格子春宣,每個(gè)格子上包含一個(gè)來(lái)自有限字母表的符號(hào),紙帶可以無(wú)限伸展嫉你。
  • 一個(gè)讀寫(xiě)頭 HEAD月帝。該讀寫(xiě)頭可以在紙帶上左右移動(dòng),它能讀出當(dāng)前所指的格子上的符號(hào)幽污,并能改變當(dāng)前格子上的符號(hào)嚷辅。
  • 一套控制規(guī)則 TABLE。它根據(jù)當(dāng)前機(jī)器所處的狀態(tài)以及當(dāng)前讀寫(xiě)頭所指的格子上的符號(hào)來(lái)確定讀寫(xiě)頭下一步的動(dòng)作距误,并改變狀態(tài)寄存器的值簸搞,令機(jī)器進(jìn)入一個(gè)新的狀態(tài)。
  • 一個(gè)狀態(tài)寄存器准潭。它用來(lái)保存圖靈機(jī)當(dāng)前所處的狀態(tài)趁俊。

雖然 lambda 演算與圖靈機(jī)在后來(lái)被證明是等價(jià)的,但兩個(gè)理論的命運(yùn)卻大不相同刑然。受限于當(dāng)時(shí)的硬件技術(shù)以及經(jīng)濟(jì)條件寺擂,lambda 演算難以在工業(yè)上落地,歷史最終選擇了圖靈機(jī)理論泼掠,而在此基礎(chǔ)上的馮·諾依曼架構(gòu)也成為第一臺(tái)計(jì)算機(jī)的設(shè)計(jì)方案怔软,匯編語(yǔ)言、C語(yǔ)言等編程語(yǔ)言都是基于此架構(gòu)被發(fā)明出來(lái)的择镇。

20世紀(jì)50年代挡逼,MIT 的教授 John McCarthy 發(fā)布了 LISP(List Processor) 語(yǔ)言,在馮·諾依曼計(jì)算機(jī)上實(shí)現(xiàn)了 lambda 演算腻豌,之后函數(shù)式編程才開(kāi)始出現(xiàn)在計(jì)算機(jī)領(lǐng)域挚瘟。

函數(shù)式編程的本質(zhì)

函數(shù)式編程是對(duì) lambda 演算的實(shí)現(xiàn),當(dāng)你使用函數(shù)式編程時(shí)饲梭,就像 lambda 演算那樣乘盖,你要將你的程序視為一個(gè)巨大的表達(dá)式,你需要用一個(gè)又一個(gè)的函數(shù)構(gòu)建出這樣的表達(dá)式憔涉,而表達(dá)式的求值過(guò)程就是程序的運(yùn)行過(guò)程订框。

但函數(shù)式編程并沒(méi)有100%還原lambda 演算,畢竟它是數(shù)學(xué)領(lǐng)域的模型兜叨,并不是為計(jì)算機(jī)領(lǐng)域貼身打造的穿扳,現(xiàn)有的函數(shù)式編程語(yǔ)言也對(duì)其進(jìn)行了一定程度的擴(kuò)展衩侥,例如支持 I/O 操作等等,使其更貼近于生產(chǎn)實(shí)踐矛物,所以如果你不是一個(gè)原教旨主義者茫死,你大可將函數(shù)式編程看成是一種編程理念,將其運(yùn)用到合適的地方去履羞,而非一成不變地遵守教條峦萎。

Wiki 上對(duì)函數(shù)式編程的定義如下:

In computer science, functional programming is a programming paradigm—a style of building the structure and elements of computer programs—that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data.

簡(jiǎn)單翻譯下,函數(shù)式編程就是將計(jì)算機(jī)的運(yùn)算過(guò)程視為數(shù)學(xué)函數(shù)的運(yùn)算(表達(dá)式求值)忆首,并且避免狀態(tài)以及數(shù)據(jù)的改變爱榔。想要理解上述定義,需要我們理解幾個(gè)關(guān)鍵詞:函數(shù)糙及、不變的數(shù)據(jù)以及狀態(tài)详幽。

純函數(shù)

由于函數(shù)式編程基于 lambda 演算,所以它的函數(shù)是數(shù)學(xué)意義上的函數(shù)(mathematical function)浸锨,這和我們?cè)诿钍骄幊讨杏玫降暮瘮?shù)不同唇聘,而后者稱(chēng)為 subroutine 更恰當(dāng)一些。同志們可以回想一下高中時(shí)代的數(shù)學(xué)知識(shí):函數(shù) f 表示一種運(yùn)算法則柱搜、一種映射關(guān)系迟郎,對(duì)于給定的輸入 x,都有唯一確定的輸出 y 與之對(duì)應(yīng)冯凹,對(duì)于相同的輸入谎亩,永遠(yuǎn)會(huì)得到相同的結(jié)果炒嘲,這就是數(shù)學(xué)意義上的函數(shù)宇姚。而在計(jì)算機(jī)領(lǐng)域中,我們稱(chēng)之為純函數(shù)夫凸,它的主要特征如下:

  • 相同的輸入對(duì)應(yīng)著相同的輸出(也被稱(chēng)為引用透明性)

  • 函數(shù)不受外部因素影響

  • 函數(shù)的執(zhí)行過(guò)程也不會(huì)改變外部狀態(tài)

下面是純函數(shù)與非純函數(shù)的例子:

// 純函數(shù)
int addBy2(int x) {
    return x + 2;
}

// 不是純函數(shù)
int addBy2(int x) {
    globalCount++; // 改變了外部的全局變量浑劳,影響外部的狀態(tài)
    return x + 2;
}

// 不是純函數(shù)
int addBy2(int x) {
    if (todayIsFriday) { // 函數(shù)的輸出不僅依賴(lài)輸入值,還依賴(lài)外部環(huán)境
        return -1;
    } else {
        return x + 2;
    }
}

純函數(shù)是函數(shù)式編程中最基本的元素夭拌,你可以將它作為參數(shù)魔熏,也可以將它作為返回值,還可以將不同的純函數(shù)組合起來(lái)進(jìn)行運(yùn)算鸽扁,總而言之蒜绽,它被用來(lái)構(gòu)建函數(shù)式編程中的一切。

不可變數(shù)據(jù)

在函數(shù)式編程中桶现,只有常量躲雅,沒(méi)有變量,這是函數(shù)式編程的風(fēng)格骡和。熟悉命令式編程的同志們可能會(huì)有些困惑相赁,為什么要這樣設(shè)計(jì)相寇?這就需要理解函數(shù)式編程和命令式編程背后的思想。

命令式編程是對(duì)計(jì)算機(jī)的抽象钮科,它的變量代表計(jì)算機(jī)的存儲(chǔ)單元唤衫,它的命令語(yǔ)句代表對(duì)存儲(chǔ)單元的存取以及運(yùn)算,它的控制語(yǔ)句代表計(jì)算機(jī)底層硬件的跳轉(zhuǎn)指令绵脯,它的一切最終都會(huì)對(duì)應(yīng)到一條條計(jì)算機(jī)指令上去佳励。在命令式編程中,x = x + 1 是很常見(jiàn)的做法桨嫁,這個(gè)語(yǔ)句的意思是將 x 所代表的存儲(chǔ)單元的內(nèi)容取出來(lái)植兰,執(zhí)行 +1 操作,然后再放回原來(lái)的存儲(chǔ)單元璃吧,這是沒(méi)有問(wèn)題的楣导。

然而函數(shù)式編程是對(duì)數(shù)學(xué)模型的抽象,你要站在數(shù)學(xué)的角度來(lái)看待它畜挨,這樣才容易理解它的做法筒繁。函數(shù)式編程的變量指的是數(shù)學(xué)中的變量,更準(zhǔn)確地說(shuō)巴元,它是一個(gè)符號(hào)毡咏、一個(gè)名稱(chēng),在數(shù)學(xué)家看來(lái)逮刨,x = x + 1 根本不能成立呕缭,命令式編程的賦值模型在這里站不住腳,所以在函數(shù)式編程中修己,變量一經(jīng)創(chuàng)建后便不允許修改恢总。

狀態(tài)

函數(shù)式編程強(qiáng)調(diào)我們使用狀態(tài)無(wú)關(guān)、沒(méi)有副作用的純函數(shù)來(lái)編寫(xiě)程序睬愤。什么是副作用呢片仿?比如說(shuō)你在函數(shù)運(yùn)行的時(shí)候,修改了全局變量尤辱、讀寫(xiě)了數(shù)據(jù)庫(kù)砂豌、修改了某某文件的內(nèi)容等,這些都是副作用光督,都會(huì)改變狀態(tài)阳距。為什么函數(shù)式編程要極力回避狀態(tài)的改變呢?因?yàn)椴环€(wěn)定的狀態(tài)會(huì)帶來(lái)不確定性结借,而不確定性則會(huì)導(dǎo)致程序的失敗筐摘。

回憶一下自己閱讀他人代碼或是第三方開(kāi)源庫(kù)的經(jīng)歷,倘若他寫(xiě)的函數(shù)中大都是些局部變量,那讀起來(lái)還算輕松蓄拣,如果他還使用了全局變量扬虚,那可就要打起十二分精神來(lái)看了。你首先要搞懂這個(gè)全局變量是用來(lái)做什么的球恤,其次還要 Ctrl + F 在整個(gè)工程中搜一下還有哪些地方用到了全局變量辜昵,是怎么用的,相互之間會(huì)不會(huì)造成什么影響咽斧,再倒霉一點(diǎn)堪置,他還用了多線程,你還要了解它是不是線程安全的张惹,這還是遇到一個(gè)全局變量所要做的工作舀锨,如果遇到多個(gè),工作量直接翻倍宛逗,簡(jiǎn)直是聞?wù)邆囊?jiàn)者流淚??坎匿。

設(shè)想一下,如果項(xiàng)目中到處都是類(lèi)似于上面的代碼雷激,那么隨著時(shí)間的推移替蔬、功能的迭代, bug 將會(huì)層出不窮屎暇,項(xiàng)目維護(hù)和擴(kuò)展的成本都在急劇的增大承桥,最終只會(huì)走向一個(gè)結(jié)果————重構(gòu)。這里大家就會(huì)理解根悼,為什么項(xiàng)目中的老代碼幾乎沒(méi)人敢去碰凶异,就因?yàn)檫@不是狀態(tài)無(wú)關(guān)的代碼,稍有改動(dòng)便會(huì)牽一發(fā)動(dòng)全身挤巡,造成嚴(yán)重的后果剩彬。

函數(shù)式編程所使用的狀態(tài)無(wú)關(guān)的純函數(shù)就可以避免以上的問(wèn)題,因?yàn)榧兒瘮?shù)給我們帶來(lái)了確定性玄柏。純函數(shù)將狀態(tài)的改變控制在了函數(shù)的內(nèi)部襟衰,它不會(huì)影響外部的狀態(tài)贴铜,它的執(zhí)行過(guò)程也不會(huì)被外部狀態(tài)影響粪摘,無(wú)論你在何時(shí)何地執(zhí)行它,它都會(huì)給你輸出同樣的結(jié)果绍坝,因此你在任何時(shí)候都可以放心大膽的用它徘意,這就是純函數(shù)的好處。

但是還是要說(shuō)一句轩褐,副作用要怎么處理椎咧,是不是就完全拋棄了?當(dāng)然不是,如果程序完全沒(méi)有副作用勤讽,那它和廢品也沒(méi)啥區(qū)別蟋座,因?yàn)樗裁炊甲霾涣恕N覀儧](méi)有辦法離開(kāi)狀態(tài)脚牍,變化是必然的向臀,程序運(yùn)行到最后也必須要產(chǎn)生結(jié)果,我們最終還是要在某一地方響應(yīng)狀態(tài)的改變诸狭。我們利用函數(shù)式編程能夠做到的是券膀,將程序的副作用控制在盡可能小的范圍內(nèi)、控制在特定的代碼模塊中驯遇,與程序其他狀態(tài)無(wú)關(guān)的模塊隔離開(kāi)芹彬,讓難以控制的狀態(tài)變得可控。

函數(shù)式編程的特性

除了上面介紹的函數(shù)式編程的基本概念叉庐,還有一些很重要的特性需要我們理解舒帮,其中一個(gè)便是高階函數(shù)。

高階函數(shù)

高階函數(shù)是指將函數(shù)作為參數(shù)或是返回值的函數(shù)陡叠,在函數(shù)式編程中你會(huì)經(jīng)常與它打交道会前。下面是一個(gè)簡(jiǎn)單的例子:

def addBy1(value):
    return value + 1
    
def addBy2(value):
    return value + 2
    
def addBy3(value):
    return value + 3

arg = 10

print addBy1(arg)
print addBy2(arg)
print addBy3(arg)

假如有3個(gè)函數(shù),它們的作用分別是把參數(shù)+1匾竿、+2瓦宜、+3,我舉的例子就是這么簡(jiǎn)單??岭妖,不用高階函數(shù)的話临庇,就會(huì)像上面那樣定義3個(gè)函數(shù),每個(gè)函數(shù)都很簡(jiǎn)單昵慌,但又很啰嗦假夺,如果之后有+4、+5斋攀、... +100的需求已卷,上述的函數(shù)定義會(huì)充斥整個(gè)文件。有沒(méi)有更為統(tǒng)一的方法呢淳蔼?這就需要高階函數(shù)了:

def addBy(value):
    def sum(arg):
        return arg + value
    return sum

addBy1 = addBy(1)
addBy2 = addBy(2)
addBy3 = addBy(3)

arg = 10

print addBy1(arg)
print addBy2(arg)
print addBy3(arg)

我們創(chuàng)造了高階函數(shù) addBy侧蘸,它的內(nèi)部定義了用來(lái)做加法的 sum 函數(shù),并將 sum 函數(shù)當(dāng)做返回值鹉梨。sum 函數(shù)會(huì)保留 addBy 函數(shù)的參數(shù) value 作為加法的一部分讳癌,這樣的話 sum 函數(shù)就會(huì)對(duì)傳入的參數(shù)直接進(jìn)行 +value 操作,方便我們的使用存皂。既便以后會(huì)有 +4晌坤、+5的需求,我們也可以使用 addBy 函數(shù)輕松定制出來(lái)。

上面是高階函數(shù)用作函數(shù)模板的一個(gè)例子骤菠,高階函數(shù)還有很多其他的用途它改,例如依賴(lài)注入等等,靈活的使用它會(huì)極大地便利我們使用函數(shù)式編程商乎。

柯里化

柯里化是 Currying 音譯過(guò)來(lái)的搔课,Wiki 上有這樣的定義:

In mathematics and computer science, currying is the technique of translating the evaluation of a function that takes multiple arguments (or a tuple of arguments) into evaluating a sequence of functions, each with a single argument.

簡(jiǎn)單來(lái)說(shuō)就是將接受多個(gè)參數(shù)的函數(shù)轉(zhuǎn)化成接受一個(gè)參數(shù)的函數(shù)。為什么要這樣做呢截亦?因?yàn)楹瘮?shù)式編程基于 lambda 演算爬泥,而 lambda 演算中的函數(shù)只接受一個(gè)參數(shù),但是如果我想要傳入多個(gè)參數(shù)要怎么辦呢崩瓤?這時(shí)候柯里化技術(shù)就登場(chǎng)了袍啡。假設(shè)我有這樣一個(gè)需求,一個(gè)函數(shù)接受3個(gè)參數(shù):i却桶、j境输、k,我需要把它們相加并將結(jié)果返回:

def fun1(i, j, k):
    return i + j + k

print  fun1(1,2,3)

那現(xiàn)在我要將其轉(zhuǎn)換成只接受一個(gè)參數(shù)的函數(shù)颖系,柯里化技術(shù)要怎么做呢嗅剖?那首先是定義一個(gè)接受 i 參數(shù)的函數(shù),然后在內(nèi)部返回一個(gè)接受 j 參數(shù)的函數(shù)嘁扼,最后這個(gè)函數(shù)再返回一個(gè)接受 k 參數(shù)的函數(shù)信粮,就跟套娃娃一樣:

def fun1(i):
    def fun2(j):
        def fun3(k):
            return i + j + k
        return fun3
    return fun2

print fun1(1)(2)(3)

關(guān)于柯里化技術(shù)的背景,大家可以參照 Wiki 了解下趁啸,而且因?yàn)橛玫娜硕嗔饲吭担吕锘夹g(shù)也玩出了很多花樣,包括惰性求值不傅、參數(shù)復(fù)用等旅掂,感興趣的話可以看下這篇文章,本文就不多講了访娶。

map && reduce

如果你想要更進(jìn)一步的貫徹函數(shù)式編程思想商虐,你首先要做的就是使用 map、reduce 來(lái)替換程序中的循環(huán)控制語(yǔ)句崖疤。為什么呢秘车?因?yàn)楹瘮?shù)式編程要求使用表達(dá)式來(lái)進(jìn)行運(yùn)算,表達(dá)式是要有輸入和輸出的戳晌,而循環(huán)控制語(yǔ)句并不具備這一點(diǎn)鲫尊,不能稱(chēng)為表達(dá)式痴柔。

map 以及 reduce 的用法如下:

strings = ["a", "ab", "abc"]

# map
print map(len, strings) # [1, 2, 3]

# 等價(jià)于下面的代碼
for value in strings:
    print len(value)
strings = ["a", "ab", "abc"]

# reduce
print reduce(lambda x, y: x+y, strings)  # aababc

# 等價(jià)于下面的代碼
str = ""
for value in strings:
    str += value
print str

相對(duì)于傳統(tǒng)的循環(huán)控制語(yǔ)句沦偎,map 以及 reduce 要顯得更為簡(jiǎn)潔、易讀,它們其實(shí)就是經(jīng)過(guò)高度抽象豪嚎、提煉出來(lái)的循環(huán)控制語(yǔ)句的模板搔驼,你只要傳進(jìn)去一組數(shù)據(jù)以及相應(yīng)的迭代操作即可,不需要寫(xiě)一堆麻煩的 for侈询、while 語(yǔ)句以及中間的臨時(shí)變量舌涨,map、 reduce 不僅使得編程更為高效扔字,而且也更加符合函數(shù)式編程風(fēng)格囊嘉。以下代碼出自這篇文章,方便大家更好的體會(huì) map && reduce 的高效:

# 計(jì)算數(shù)組中正數(shù)的平均值

num =[2, -5, 9, 7, -2, 5, 3, 1, 0, -3, 8]
positive_num_cnt = 0
positive_num_sum = 0
for i in range(len(num)):
    if num[i] > 0:
        positive_num_cnt += 1
        positive_num_sum += num[i]
 
if positive_num_cnt > 0:
    average = positive_num_sum / positive_num_cnt
 
print average
# 輸出 5
# 如果用函數(shù)式編程革为,這個(gè)例子可以寫(xiě)成這樣:
positive_num = filter(lambda x: x>0, num)
average = reduce(lambda x,y: x+y, positive_num) / len( positive_num )

pipeline

pipeline 技術(shù)是指流水線技術(shù)扭粱,它可以將多個(gè)函數(shù)串聯(lián)起來(lái),前一個(gè)函數(shù)的輸出可以作為下一個(gè)函數(shù)的輸入震檩,就像工廠里的流水線一樣琢蛤,我們的輸入經(jīng)過(guò)多個(gè)函數(shù)的處理后,最終會(huì)得到我們想要的輸出結(jié)果抛虏。

函數(shù)式編程要求我們將一個(gè)又一個(gè)的純函數(shù)組合成表達(dá)式來(lái)進(jìn)行運(yùn)算博其,如果沒(méi)有流水線技術(shù),我們很容易就寫(xiě)出如下的包菜式代碼:

# 1. 找出偶數(shù)迂猴。
# 2. 乘以3
# 3. 轉(zhuǎn)成字符串返回

def even_filter(nums):
    return filter(lambda x: x%2==0, nums)
 
def multiply_by_three(nums):
    return map(lambda x: x*3, nums)
 
def convert_to_string(nums):
    return map(lambda x: 'The Number: %s' % x,  nums)
 
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
pipeline = convert_to_string( multiply_by_three(even_filter(nums)))
for num in pipeline:
    print num

而使用了 pipeline 技術(shù)后慕淡,只要這樣做:

nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
force(nums | even_filter | multiply_by_three | convert_to_string | echo)

pipeline 技術(shù)的代碼如下:

class Pipe(object):
    def __init__(self, func):
        self.func = func
 
    def __ror__(self, other):
        def generator():
            for obj in other:
                if obj is not None:
                    yield self.func(obj)
        return generator()
 
@Pipe
def even_filter(num):
    return num if num % 2 == 0 else None
 
@Pipe
def multiply_by_three(num):
    return num*3
 
@Pipe
def convert_to_string(num):
    return 'The Number: %s' % num
 
@Pipe
def echo(item):
    print item
    return item
 
def force(sqs):
    for item in sqs: pass

上面的示例代碼來(lái)自于這里,我自己寫(xiě)的例子怕是太簡(jiǎn)單會(huì)誤導(dǎo)大家沸毁,所以在網(wǎng)上眾多的資料中摘取了這段質(zhì)量較好的代碼示例來(lái)幫助大家理解??儡率。

總結(jié)

函數(shù)式編程講到這里就告一段落了,相信讀到這里以清,大家已經(jīng)對(duì)函數(shù)式編程的思想有了大概的認(rèn)識(shí)儿普,但是如果想要更深入的了解函數(shù)式編程的話,選擇一門(mén)函數(shù)式編程語(yǔ)言來(lái)實(shí)踐是最容易的方法了掷倔,當(dāng)然眉孩,lambda 演算的學(xué)習(xí)也是必不可少的,這會(huì)讓你更加深刻的認(rèn)識(shí)函數(shù)式編程思想勒葱。

以下是一些參考資料:

總算寫(xiě)完了浪汪,可累死我了??????????。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末凛虽,一起剝皮案震驚了整個(gè)濱河市死遭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌凯旋,老刑警劉巖呀潭,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钉迷,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡钠署,警方通過(guò)查閱死者的電腦和手機(jī)糠聪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)谐鼎,“玉大人舰蟆,你說(shuō)我怎么就攤上這事±旯鳎” “怎么了身害?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)草戈。 經(jīng)常有香客問(wèn)我题造,道長(zhǎng),這世上最難降的妖魔是什么猾瘸? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任界赔,我火速辦了婚禮,結(jié)果婚禮上牵触,老公的妹妹穿的比我還像新娘淮悼。我一直安慰自己,他們只是感情好揽思,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布袜腥。 她就那樣靜靜地躺著,像睡著了一般钉汗。 火紅的嫁衣襯著肌膚如雪羹令。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,370評(píng)論 1 302
  • 那天损痰,我揣著相機(jī)與錄音福侈,去河邊找鬼。 笑死卢未,一個(gè)胖子當(dāng)著我的面吹牛肪凛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播辽社,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼伟墙,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了滴铅?” 一聲冷哼從身側(cè)響起戳葵,我...
    開(kāi)封第一講書(shū)人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎汉匙,沒(méi)想到半個(gè)月后拱烁,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體生蚁,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年邻梆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了守伸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绎秒。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡浦妄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出见芹,到底是詐尸還是另有隱情剂娄,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布玄呛,位于F島的核電站阅懦,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏徘铝。R本人自食惡果不足惜耳胎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望惕它。 院中可真熱鬧怕午,春花似錦、人聲如沸淹魄。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)甲锡。三九已至兆蕉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間缤沦,已是汗流浹背虎韵。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留缸废,地道東北人劝术。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像呆奕,于是被迫代替她去往敵國(guó)和親养晋。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

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