免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
好書丨為什么函數(shù)式編程最近才崛起


小貼士


參與文末話題討論,有機(jī)會獲得贈書~


導(dǎo)語:函數(shù)式編程并不是新概念,實際上,在計算機(jī)科學(xué)出現(xiàn)之初,函數(shù)式編程就已經(jīng)嶄露頭角,教科書式的函數(shù)式編程語言LISP在1958年就誕生了,但是,為什么一直都是命令式編程和面向?qū)ο缶幊檀笮衅涞滥兀?/span>


函數(shù)式編程歷史

說來話長,想當(dāng)年,阿蘭·圖靈和馮·諾依曼祖師爺開天辟地,創(chuàng)立了計算機(jī)這門學(xué)科,因為這行前無古人,所以最早的一批學(xué)者都有其他專業(yè)的背景,有的是電子電氣方面的專家,有來自物理學(xué)科,還有的本來是數(shù)學(xué)家。不同的背景,也就帶來了對計算機(jī)發(fā)展方向的不同觀點。


當(dāng)時,數(shù)學(xué)家們提出的編程語言模型自然具有純數(shù)學(xué)的氣質(zhì),也是最優(yōu)雅、最易于管理的解決方法。這其中的代表人物就是阿隆佐·邱奇(Alonzo Church),邱奇在計算機(jī)誕生之前就提出Lambda演算(Lambda Calculus)的概念,也就是用純函數(shù)的組合來描述計算過程。根據(jù)Lambda演算,如果一個問題能夠用一套函數(shù)組合的算法來描述,那就說明這個問題是可計算的,很自然,也就可以用編程語言的函數(shù)組合的方式來實現(xiàn)這樣的計算過程。


可是,數(shù)學(xué)家們的理念,并沒有在計算機(jī)發(fā)展初期被大范圍應(yīng)用,為什么呢?因為當(dāng)時的硬件制造技術(shù)還很不發(fā)達(dá),電子元件遠(yuǎn)沒有當(dāng)今這樣的水平,那時候每一個電子元件制造成本高,而且體積大,無法在一小片芯片上放置很多元件,無論是運算元件還是存儲元件,都是又慢又貴。


既然物理硬件昂貴,那么只好省著點用了,這種情況下,和硬件靠得最近的物理學(xué)家和電子電氣工程師們掌握了編程語言的主流方向,命令式編程就是這樣發(fā)展起來的。


早期的編程工作中,程序員必須考慮硬件的架構(gòu),如何使用CPU計算資源,如何巧妙利用有限的那么幾個寄存器(register),如果不考慮的話,性能肯定無法過關(guān)。在這樣的硬件條件下,函數(shù)式編程的想法要實現(xiàn),只能通過一層軟件模擬來復(fù)現(xiàn)數(shù)學(xué)家設(shè)想的模型,這多出來的一層無疑要耗費性能,所以光是性能這一個因素,就讓函數(shù)式編程的實踐難以推廣。


還好,電子技術(shù)在飛速發(fā)展,計算機(jī)的運算能力和存儲能力不斷提高。1965年,電子芯片公司Intel的創(chuàng)始人戈登·摩爾根據(jù)觀察,做了這樣的斷言:“當(dāng)價格不變時,集成電路上可容納的元器件的數(shù)目,約每隔18~24個月便會增加一倍,性能也將提升一倍?!边@也就是著名的“摩爾定律”,根據(jù)這個定律,計算機(jī)的計算能力是以指數(shù)趨勢增長,從那之后很長一段時間,軟件行業(yè)也一直在享受計算能力增長帶來的紅利。


但是,進(jìn)入21世紀(jì)之后,大家發(fā)現(xiàn)“摩爾定律”漸漸不管用了,集成電路上的元器件數(shù)目不能增長得這么快,因為,電子部件的密度快要達(dá)到物理極限了,一個集成電路上沒法聚集更多的器件,雖然工程師們還在進(jìn)一步提高CPU的性能,但是,普遍認(rèn)同的觀點是,單核的運算能力不可能保持摩爾定律的增長速度。


這時候,芯片的發(fā)展方向轉(zhuǎn)為多核,軟件架構(gòu)也向分布式方向發(fā)展。這種轉(zhuǎn)化很合理,既然一個核一秒鐘只能做N次運算,那么我用8個核,一秒就能進(jìn)行8*N次運算;同樣,一個CPU中核的數(shù)量雖然是有限的,但是可以把計算量分布在不同的計算機(jī)上,假如一臺計算機(jī)一秒鐘的運算能力是N,那么1000臺計算機(jī),一秒鐘的計算能力就是1000*N。


既然硬件的解決方案只能如此,剩下的唯一問題就是,如何把運算分布到不同的核或者不同的計算機(jī)上去呢?如果是用命令式編程,真的很難,因為編寫協(xié)調(diào)多核或者分布式的任務(wù)處理程序非常困難,讓每個開發(fā)者都做這樣的工作,那真是非常不現(xiàn)實;然而,函數(shù)式編程卻能夠讓大部分開發(fā)者不需要操心任務(wù)處理,所以非常適合分布式計算的場景。


聲明式的函數(shù),讓開發(fā)者只需要表達(dá)“想要做什么”,而不需要表達(dá)“怎么去做”,這樣就極大地簡化了開發(fā)者的工作。至于具體“怎么去做”,讓專門的任務(wù)協(xié)調(diào)框架去實現(xiàn),這個框架可以靈活地分配工作給不同的核、不同的計算機(jī),而開發(fā)者不必關(guān)心框架背后發(fā)生了什么。


與此同時,計算機(jī)業(yè)界也發(fā)現(xiàn),隨著CPU性能和存儲設(shè)備性能的提高,當(dāng)初導(dǎo)致函數(shù)式編程性能問題的障礙,現(xiàn)在都不是問題了,這也給函數(shù)式編程崛起增加了助推力。


可能讀者會問,基于現(xiàn)在的計算機(jī)硬件架構(gòu),用函數(shù)式編程寫出的程序,肯定性能會比命令式編程寫出來的要低一些吧?其實未必。首先,當(dāng)今軟件已經(jīng)是一個很復(fù)雜的系統(tǒng),性能并不完全由是否更直接翻譯為機(jī)器語言決定。其次,在性能相當(dāng)?shù)那闆r下,軟件的開發(fā)速度要比運行速度重要得多。打個比方,用命令式編程,開發(fā)一個網(wǎng)絡(luò)服務(wù)花費6個月,每個請求處理時間是1毫秒;用函數(shù)式編程,開發(fā)同樣的網(wǎng)絡(luò)服務(wù)花費3個月,每個請求處理時間是10毫秒,是否值得花3個月去獲得這9毫秒的性能增長呢?


要知道,從客戶端感知到的反應(yīng)速度,不光包含服務(wù)器端的計算處理時間,還包含網(wǎng)絡(luò)傳輸時間,比如平均網(wǎng)絡(luò)傳輸時間是200毫秒,200毫秒是一個比較正常的網(wǎng)絡(luò)延遲,那么訪問命令式編程服務(wù)的反應(yīng)時間是201毫秒,訪問函數(shù)式編程服務(wù)的反應(yīng)時間是210毫秒。201毫秒和210毫秒,用戶感知的性能沒有那么大的區(qū)別,這時候,我們當(dāng)然更愿意選擇能夠提高開發(fā)速度的方法。


語言演進(jìn)


除了硬件性能和軟件開發(fā)需求的推動,語言的演進(jìn)也是推動函數(shù)式編程被接受的一大動因。


曾幾何時,只有Haskell和LISP這樣的純函數(shù)式編程語言才高舉這面大旗,但是后來,一些本來屬于命令式陣營或者面向?qū)ο箨嚑I的編程語言也開始添加函數(shù)式的特性,這樣,更多的開發(fā)者能夠接觸到函數(shù)式這種編程思想。增加了函數(shù)式特性的這些語言,當(dāng)然包括JavaScript。


如果要學(xué)習(xí)最正統(tǒng)的函數(shù)式編程,比如Haskell,可能需要極大的耐心,因為學(xué)習(xí)過程中要涉及很多數(shù)學(xué)概念和推演,在開始實踐函數(shù)式編程之前,就要面對這么龐大的背景知識,很有可能學(xué)著學(xué)著就睡著了。在《深入淺出RxJS》中,不會灌輸給讀者繁復(fù)的數(shù)學(xué)理論,而是盡量用淺顯易懂的語言和代碼示例來介紹函數(shù)式編程,空有理論沒有實踐是無意義的。


函數(shù)式編程和面向?qū)ο缶幊痰谋容^


要介紹函數(shù)式編程(Functional Programming)就不得不拿另一個編程范式面向?qū)ο缶幊蹋∣bject Oriented Programming)作對比,因為面向?qū)ο缶幊淘?jīng)統(tǒng)治了業(yè)界很長一段時間,而函數(shù)式編程正在逐漸挑戰(zhàn)面向?qū)ο蟮牡匚弧?/span>


這兩種編程方式都可以讓代碼更容易理解,不過方式不同。簡單說來,面向?qū)ο蟮姆椒ò褷顟B(tài)的改變封裝起來,以此達(dá)到讓代碼清晰的目的;而函數(shù)式編程則是盡量減少變化的部分,以此讓代碼邏輯更加清晰。


面向?qū)ο蟮乃枷胧前褦?shù)據(jù)封裝在類的實例對象中,把數(shù)據(jù)藏起來,讓外部不能直接操作這些對象,只能通過類提供的實例方法來讀取和修改這些數(shù)據(jù),這樣就限制了對數(shù)據(jù)的訪問方式。對于毫無節(jié)制任意修改數(shù)據(jù)的編程方式,面向?qū)ο鬅o疑是巨大的進(jìn)步,因為通過定義類的方法,可以控制對數(shù)據(jù)的操作。


但是,面向?qū)ο箅[藏數(shù)據(jù)的特點,帶來了一個先天的缺陷,就是數(shù)據(jù)的修改歷史完全被隱藏了。有人說,面向?qū)ο缶幊烫峁┝艘环N持續(xù)編寫爛代碼的方式,它讓你通過一系列補(bǔ)丁來拼湊程序。這話有點過激,但是也道出了面向?qū)ο缶幊痰娜秉c。


當(dāng)我們在代碼中看到一個對象實例的時候,即使知道了對象的當(dāng)前狀態(tài),也沒法知道這個對象是如何一步一步走到這個狀態(tài)的,這種不確定性導(dǎo)致代碼可維護(hù)性下降。


函數(shù)式編程中,傾向于數(shù)據(jù)就是數(shù)據(jù),函數(shù)就是函數(shù),函數(shù)可以處理數(shù)據(jù),也是并不像面向?qū)ο蟮念惛拍钜粯影褦?shù)據(jù)和函數(shù)封在一起,而是讓每個函數(shù)都不要去修改原有數(shù)據(jù)(不可變性),而且通過產(chǎn)生新的數(shù)據(jù)來作為運算結(jié)果(純函數(shù))。


本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
這可能是最全的計算機(jī)編程語言列表了
面向?qū)ο缶幊陶Z言中的函數(shù)式編程--為命令模式和訪問者模式正名
再談編程范式
函數(shù)式編程(FP)
Java程序員在寫SQL程序時候常犯的10個錯誤
幫你提升 Python 的 27 種編程語言
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服