青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

chenglong7997

函數(shù)式編程初探

誕生50多年之后,函數(shù)式編程(functional programming)開(kāi)始獲得越來(lái)越多的關(guān)注。 

不僅最古老的函數(shù)式語(yǔ)言Lisp重獲青春,而且新的函數(shù)式語(yǔ)言也層出不窮,比如Erlang、Clojure、Scala,、F#等等。目前最當(dāng)紅的Python、Ruby、Javascript,對(duì)函數(shù)式編程的支持都很強(qiáng),就連老牌的面向?qū)ο蟮腏ava、面向過(guò)程的PHP,都忙不迭地加入對(duì)匿名函數(shù)的支持。越來(lái)越多的跡象表明,函數(shù)式編程已經(jīng)不再只是學(xué)術(shù)界的最?lèi)?ài),也開(kāi)始大踏步地在業(yè)界投入使用。 

也許繼"面向?qū)ο缶幊?之后,"函數(shù)式編程"會(huì)成為下一個(gè)編程的主流范式。未來(lái)的程序員恐怕或多或少都必須懂一點(diǎn)。 

但是,"函數(shù)式編程"看上去比較難,缺乏通俗的入門(mén)教程,各種介紹文章都充斥著數(shù)學(xué)符號(hào)和專(zhuān)用術(shù)語(yǔ),讓人讀了如墜云霧。就連最基本的問(wèn)題"什么是函數(shù)式編程?",網(wǎng)上都搜不到易懂的回答。 

下面是我(指本文作者阮一峰)的"函數(shù)式編程"學(xué)習(xí)筆記,分享出來(lái),與大家一起探討。內(nèi)容不涉及數(shù)學(xué)(Lambda Calculus我也不懂),也不涉及高級(jí)特性(比如lazy evaluationcurrying),只求盡量簡(jiǎn)單通俗地整理和表達(dá),我現(xiàn)在所理解的"函數(shù)式編程"以及它的意義。 

我主要參考了Slava Akhmechet的"Functional Programming For The Rest of Us"一文。 

一、定義 

簡(jiǎn)單說(shuō),"函數(shù)式編程"是一種"編程范式",也就是如何編寫(xiě)程序的方法論。 

它屬于"結(jié)構(gòu)化編程"的一種,主要思想是把運(yùn)算過(guò)程盡量寫(xiě)成一系列嵌套的函數(shù)調(diào)用。舉例來(lái)說(shuō),現(xiàn)在有這樣一個(gè)數(shù)學(xué)表達(dá)式: 

(1 + 2) * 3 - 4 

傳統(tǒng)的過(guò)程式編程,可能這樣寫(xiě): 
代碼 
  1. var a = 1 + 2;  
  2.   
  3. var b = a * 3;  
  4.   
  5. var c = b - 4;  

函數(shù)式編程要求使用函數(shù),我們可以把運(yùn)算過(guò)程定義為不同的函數(shù),然后寫(xiě)成下面這樣: 
代碼 
  1. var result = subtract(multiply(add(1,2), 3), 4);  

這就是函數(shù)式編程。 

二、特點(diǎn) 

函數(shù)式編程具有五個(gè)鮮明的特點(diǎn)。 

1、函數(shù)是"第一等公民" 

所謂"第一等公民"(first class),指的是函數(shù)與其他數(shù)據(jù)類(lèi)型一樣,處于平等地位,可以賦值給其他變量,也可以作為參數(shù),傳入另一個(gè)函數(shù),或者作為別的函數(shù)的返回值。 

舉例來(lái)說(shuō),下面代碼中的print變量就是一個(gè)函數(shù),可以作為另一個(gè)函數(shù)的參數(shù)。 
代碼 
  1. var print = function(i){ console.log(i);};  
  2.   
  3. [1,2,3].forEach(print);  

2、只用"表達(dá)式",不用"語(yǔ)句" 

"表達(dá)式"是一個(gè)單純的運(yùn)算過(guò)程,總是有返回值;"語(yǔ)句"是執(zhí)行某種操作,沒(méi)有返回值。函數(shù)式編程要求,只使用表達(dá)式,不使用語(yǔ)句。也就是說(shuō),每一步都是單純的運(yùn)算,而且都有返回值。 

原因是函數(shù)式編程的開(kāi)發(fā)動(dòng)機(jī),一開(kāi)始就是為了處理運(yùn)算,不考慮系統(tǒng)的讀寫(xiě)(I/O)。"語(yǔ)句"屬于對(duì)系統(tǒng)的讀寫(xiě)操作,所以就被排斥在外。 

當(dāng)然,實(shí)際應(yīng)用中,不做I/O是不可能的。因此,編程過(guò)程中,函數(shù)式編程只要求把I/O限制到最小,不要有不必要的讀寫(xiě)行為,保持計(jì)算過(guò)程的單純性。 

3、沒(méi)有"副作用" 

所謂"副作用"(side effect),指的是函數(shù)內(nèi)部與外部互動(dòng)(最典型的情況,就是修改全局變量的值),產(chǎn)生運(yùn)算以外的其他結(jié)果。 

函數(shù)式編程強(qiáng)調(diào)沒(méi)有"副作用",意味著函數(shù)要保持獨(dú)立,所有功能就是返回一個(gè)新的值,沒(méi)有其他行為,尤其是不得修改外部變量的值。 

4、不修改狀態(tài) 

上一點(diǎn)已經(jīng)提到,函數(shù)式編程只是返回新的值,不修改系統(tǒng)變量。因此,不修改變量,也是它的一個(gè)重要特點(diǎn)。

在其他類(lèi)型的語(yǔ)言中,變量往往用來(lái)保存"狀態(tài)"。不修改變量,意味著狀態(tài)不能保存在變量中。函數(shù)式編程使用參數(shù)保存狀態(tài),最好的例子就是遞歸。下面的代碼是一個(gè)將字符串逆序排列的函數(shù),它演示了不同的參數(shù)如何決定了運(yùn)算所處的"狀態(tài)"。 
代碼 
  1. function reverse(string) {  
  2.   
  3.     if(string.length == 0)  
  4.         {  
  5.       return string;  
  6.     }   
  7.         else   
  8.         {  
  9.            return reverse(string.substring(1, string.length)) + string.substring(01);  
  10.     }  
  11.   
  12.   }  

由于使用了遞歸,函數(shù)式語(yǔ)言的運(yùn)行速度比較慢,這是它長(zhǎng)期不能在業(yè)界推廣的主要原因。 

5、引用透明 

引用透明(Referential transparency),指的是函數(shù)的運(yùn)行不依賴(lài)于外部變量或"狀態(tài)",只依賴(lài)于輸入的參數(shù),任何時(shí)候只要參數(shù)相同,引用函數(shù)所得到的返回值總是相同的。 
有了前面的第三點(diǎn)和第四點(diǎn),這點(diǎn)是很顯然的。其他類(lèi)型的語(yǔ)言,函數(shù)的返回值往往與系統(tǒng)狀態(tài)有關(guān),不同的狀態(tài)之下,返回值是不一樣的。這就叫"引用不透明",很不利于觀察和理解程序的行為。 

三、意義 

函數(shù)式編程到底有什么好處,為什么會(huì)變得越來(lái)越流行? 

1、代碼簡(jiǎn)潔,開(kāi)發(fā)快速 

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

Paul Graham在《黑客與畫(huà)家》一書(shū)中寫(xiě)道:同樣功能的程序,極端情況下,Lisp代碼的長(zhǎng)度可能是C代碼的二十分之一。 

如果程序員每天所寫(xiě)的代碼行數(shù)度基本相同,這就意味著,"C語(yǔ)言需要一年時(shí)間完成開(kāi)發(fā)某個(gè)功能,Lisp語(yǔ)言只需要不到三星期。反過(guò)來(lái)說(shuō),如果某個(gè)新功能,Lisp語(yǔ)言完成開(kāi)發(fā)需要三個(gè)月,C語(yǔ)言需要寫(xiě)五年。"當(dāng)然,這樣的對(duì)比故意夸大了差異,但是"在一個(gè)高度競(jìng)爭(zhēng)的市場(chǎng)中,即使開(kāi)發(fā)速度只相差兩三倍,也足以使得你永遠(yuǎn)處在落后的位置。" 

2、接近自然語(yǔ)言,易于理解 

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

前文曾經(jīng)將表達(dá)式(1 + 2) * 3 - 4,寫(xiě)成函數(shù)式語(yǔ)言: 

代碼 
  1. subtract(multiply(add(1,2), 3), 4)  

對(duì)它進(jìn)行變形,不難得到另一種寫(xiě)法: 
代碼 
  1. add(1,2).multiply(3).subtract(4)  

這基本就是自然語(yǔ)言的表達(dá)了。再看下面的代碼,大家應(yīng)該一眼就能明白它的意思吧: 
代碼 
  1. merge([1,2],[3,4]).sort().search("2")  

3、更方便的代碼管理 

函數(shù)式編程不依賴(lài)、也不會(huì)改變外界的狀態(tài),只要給定輸入?yún)?shù),返回的結(jié)果必定相同。因此,每一個(gè)函數(shù)都可以被看做獨(dú)立單元,很有利于進(jìn)行單元測(cè)試(unit testing)和除錯(cuò)(debugging),以及模塊化組合。 

4、易于"并發(fā)編程" 

函數(shù)式編程不需要考慮"死鎖"(deadlock),因?yàn)樗恍薷淖兞浚愿静淮嬖?鎖"線程的問(wèn)題。不必?fù)?dān)心一個(gè)線程的數(shù)據(jù),被另一個(gè)線程修改,所以可以很放心地把工作分?jǐn)偟蕉鄠€(gè)線程,部署"并發(fā)編程"(concurrency)。 

請(qǐng)看下面的代碼: 
代碼 
  1. var s1 = Op1();  
  2.   
  3. var s2 = Op2();  
  4.   
  5. var s3 = concat(s1, s2);  

由于s1和s2互不干擾,不會(huì)修改變量,誰(shuí)先執(zhí)行是無(wú)所謂的,所以可以放心地增加線程,把它們分配在兩個(gè)線程上完成。其他類(lèi)型的語(yǔ)言就做不到這一 點(diǎn),因?yàn)閟1可能會(huì)修改系統(tǒng)狀態(tài),而s2可能會(huì)用到這些狀態(tài),所以必須保證s2在s1之后運(yùn)行,自然也就不能部署到其他線程上了。 

多核CPU是將來(lái)的潮流,所以函數(shù)式編程的這個(gè)特性非常重要。 

5、代碼的熱升級(jí) 

函數(shù)式編程沒(méi)有副作用,只要保證接口不變,內(nèi)部實(shí)現(xiàn)是外部無(wú)關(guān)的。所以,可以在運(yùn)行狀態(tài)下直接升級(jí)代碼,不需要重啟,也不需要停機(jī)。Erlang語(yǔ)言早就證明了這一點(diǎn),它是瑞典愛(ài)立信公司為了管理電話系統(tǒng)而開(kāi)發(fā)的,電話系統(tǒng)的升級(jí)當(dāng)然是不能停機(jī)的。 

posted on 2012-04-09 01:48 Snape 閱讀(376) 評(píng)論(0)  編輯 收藏 引用 所屬分類(lèi): distributed system

導(dǎo)航

<2025年9月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

統(tǒng)計(jì)

常用鏈接

留言簿

隨筆分類(lèi)

隨筆檔案

文章分類(lèi)

文章檔案

my

搜索

最新評(píng)論

閱讀排行榜

評(píng)論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美与欧洲交xxxx免费观看| 亚洲永久视频| 男女视频一区二区| 免费一级欧美在线大片| 欧美电影免费观看高清| 欧美凹凸一区二区三区视频| 久久久久久久性| 久久精品免费看| 国精品一区二区三区| 一区二区精品在线| 韩国视频理论视频久久| 欧美一区二区视频在线| 久久国产精品高清| 国产欧美日韩精品在线| 亚洲靠逼com| 亚洲欧美bt| 夜夜夜久久久| 99视频一区| 亚洲综合首页| 久久在线视频在线| 久久天天躁狠狠躁夜夜av| 国产精品一区二区黑丝| 亚洲精品激情| 国产欧美日韩另类一区| 亚洲人成网站777色婷婷| 国产一区二区三区不卡在线观看| 亚洲免费av电影| 亚洲视频在线观看视频| 欧美一区二区视频在线| 欧美一区二区大片| 国产精品一区毛片| 久久精品在线观看| 一本色道久久综合| 欧美激情免费观看| 美女成人午夜| 麻豆精品91| 久久婷婷久久| 久久av红桃一区二区小说| 性8sex亚洲区入口| 亚洲激情校园春色| 美国成人毛片| 99日韩精品| 国产一区二区三区成人欧美日韩在线观看| 欧美性猛交xxxx免费看久久久| 欧美精品日韩www.p站| 亚洲欧洲日产国码二区| 一区二区三区日韩欧美| 亚洲色无码播放| 国产精品www994| 久久久av网站| 亚洲视频免费| 亚洲一区二区精品| 夜夜精品视频| 亚洲精品一二三区| 老色鬼精品视频在线观看播放| 亚洲国产精品激情在线观看| 国产精品电影在线观看| 亚洲欧美激情在线视频| 鲁鲁狠狠狠7777一区二区| 韩国福利一区| 国产视频观看一区| 欧美性做爰毛片| 欧美成人免费在线观看| 亚洲午夜视频在线| 亚洲韩日在线| 欧美成人综合网站| 久久久www成人免费无遮挡大片 | 欧美日韩国产首页在线观看| 免费在线欧美视频| 午夜在线一区二区| 亚洲日本中文字幕免费在线不卡| 一区二区三区欧美日韩| 欧美一区二区福利在线| 欧美成人在线影院| 亚洲精品少妇| 欧美一区午夜精品| 欧美二区视频| 亚洲国产导航| 99re6这里只有精品视频在线观看| 久久香蕉精品| 亚洲黄色影片| 日韩一区二区精品| 久久av在线看| 国产日韩欧美在线视频观看| 亚洲欧美日韩高清| 久久亚洲视频| 国产曰批免费观看久久久| 欧美日韩一级黄| 国产视频久久久久| 亚洲性视频h| 91久久嫩草影院一区二区| 在线亚洲一区观看| 久久国产精品亚洲77777| 欧美日精品一区视频| 亚洲国产综合91精品麻豆| 久久精品国产一区二区三区免费看 | 香蕉av777xxx色综合一区| 久久九九热re6这里有精品| 99re这里只有精品6| 亚洲免费观看高清完整版在线观看熊 | 国产精品igao视频网网址不卡日韩| 亚洲另类自拍| 亚洲欧美日韩第一区| 国产亚洲精品一区二区| 欧美激情一区在线| 亚洲伦理中文字幕| 久久av一区二区三区漫画| 亚洲一区二区在线看| 在线日韩一区二区| 亚洲精品午夜| 精品成人久久| 亚洲视频你懂的| 亚洲第一二三四五区| 亚洲一区二区三区乱码aⅴ蜜桃女 亚洲一区二区三区乱码aⅴ | 欧美高清不卡| 国产精品男女猛烈高潮激情| 亚洲第一黄色网| 国产一区二区三区直播精品电影| 亚洲精品免费电影| 国产一区二区三区无遮挡| 亚洲深夜福利网站| 亚洲精品久久久久久久久| 欧美在线不卡| 欧美一级视频免费在线观看| 欧美日韩一级视频| 亚洲人成久久| 亚洲人成人99网站| 久久综合色播五月| 欧美~级网站不卡| 国内揄拍国内精品久久| 亚洲欧美日韩另类精品一区二区三区| 一区二区三区高清视频在线观看| 免费视频一区| 亚洲高清在线精品| 亚洲欧洲综合另类| 小嫩嫩精品导航| 欧美日韩中文字幕精品| 亚洲六月丁香色婷婷综合久久| 亚洲精品久久久久中文字幕欢迎你 | 欧美日韩福利视频| 亚洲国产高清aⅴ视频| 亚洲国产精品毛片| 你懂的成人av| 欧美国产一区二区| 亚洲欧洲日产国码二区| 欧美xxx在线观看| 亚洲黑丝在线| 亚洲特级片在线| 欧美性开放视频| 亚洲一品av免费观看| 欧美中文在线观看国产| 国产一区二区0| 久久亚洲春色中文字幕| 亚洲第一在线| 一区二区三区视频观看| 欧美调教视频| 亚洲欧美综合一区| 毛片一区二区三区| 一本色道久久综合狠狠躁篇怎么玩 | 日韩午夜精品视频| 欧美日韩国产经典色站一区二区三区| 亚洲欧洲日本一区二区三区| 亚洲欧美日韩国产中文在线| 国产偷国产偷亚洲高清97cao| 久久久91精品国产| 最新亚洲一区| 性色av一区二区三区红粉影视| 国产一区二区三区电影在线观看| 老司机成人网| 亚洲性人人天天夜夜摸| 免费日韩一区二区| 亚洲一区尤物| 亚洲电影在线免费观看| 国产精品成人v| 久久久综合视频| 一区二区精品在线| 美日韩丰满少妇在线观看| 亚洲天堂av综合网| 一区二区三区在线视频免费观看| 欧美精品一区三区在线观看| 午夜视黄欧洲亚洲| 亚洲麻豆av| 可以免费看不卡的av网站| 亚洲天堂男人| 亚洲欧洲精品一区二区精品久久久| 国产精品久久久久一区| 欧美黄色一级视频| 久久人人97超碰国产公开结果 | 亚洲视频图片小说| 欧美国产高潮xxxx1819| 欧美伊久线香蕉线新在线| 亚洲日本激情| 黄色成人av网站| 国产精品一区二区久久| 欧美承认网站| 久久中文字幕导航| 久久成人综合视频| 亚洲一区二区三区激情| 亚洲精品国产精品久久清纯直播 | 一本色道综合亚洲|