函数式编程的兴衰与当前之崛起
本文作者: Eric Elliott
編譯:胡子大哈
翻譯原文:http://huziketang.com/blog/posts/detail?postId=58e3062ba58c240ae35bb8de
英文連接:The Rise and Fall and Rise of Functional Programming (Composing Software)
轉載請注明出處,保留原文鏈接以及作者信息
本文是“組合式軟件”系列的一篇文章,從頭開始學習函數式編程和使用 JavaScript ES6+ 進行軟件編程。請繼續關注,后面還有很多相關內容。
在我 6 歲的時候,我每天花很多時間和我最好的朋友一起打游戲,他們家里有很多電腦。對我來講它有種魔幻版不可抗拒的力量。有一天我突然問我朋友:“我們怎樣才能自己做一個游戲呢?”
他也不知道,所以我們一起去問他的爸爸,叔叔從很高的架子上拿下來一本書:Basic。我也由此開始了我的編程之旅。后來大學都有代數這門課程,而我對它已經很熟悉了,因為編程里面代數是基礎,到處都是代數。
組合式軟件的興起
在計算機科學剛剛起步的時候,很多計算機科學的理論都還沒有落地。那時候有兩個偉大的計算機科學家:阿隆佐·丘奇和阿蘭·圖靈。他們創造了兩個不同的,但是具有同等效力的通用計算模型。兩個模型都可以計算任何可以計算的東西(著重強調,“通用”)。
阿隆佐·丘奇發明了 λ 演算, λ 演算是基于函數應用的通用計算模型。阿蘭·圖靈則因圖靈機而廣為人知。圖靈機定義了一個理論上的設備,它可以控制條帶上的符號。他們合作證明了 λ 演算和圖靈機是功能等價的。
λ 演算全部都是關于函數組合。函數組合在軟件開發中是非常富有表現力和說服力的。本文中,我們會討論函數組合在軟件設計中的重要性。
這里有三點關于 λ 演算的特殊說明:
函數通常是匿名的。在 JavaScript 中,const sum = (x, y) => x + y 的右邊是匿名函數,即 (x, y) => x + y。
λ 演算中的函數只接受單一輸入,它是一元的。如果你需要傳遞多參數,函數會接受第一個輸入并且返回一個新的函數來接受第二個參數,以此類推。一個 n 元函數 (x, y) => x + y 可以表達為一個一元函數:x => y => x + y。這種 n 元函數到一元函數的轉化叫做柯里化。
函數是一級的。意思是說一個函數可以作為另一個函數的輸入,并且一個函數可以返回另一個函數。
這些特征一起構成了簡單且容易理解的規則,在組合式軟件中使用函數作為主要編碼單元。在 JavaScript 中,匿名函數和柯里化函數都是可選特征,也就是說 JavaScript 支持 λ 演算的主要特征但是并不強制使用。
經典的函數組合是把一個函數的輸出作為另一個函數的輸入,例如下面的組合:
f·g可以寫成:
compose2 = f => g => x => f(g(x))下面是如何使用它:
double = n => n * 2inc = n => n + 1compose2(double)(inc)(3)compose2() 函數接受 double 函數作為第一個參數,inc 函數作為第二個參數,最后應用參數 3 到這兩個函數組合上。再看一下 compose2() 的聲明,f 是 double(),g 是 inc(),x 是 3。函數調用 compose2(double)(inc)(3),實際上是三個不同的函數調用:
首先傳遞 double 返回一個新函數 1;
新函數 1 以 inc 為參數并且返回一個新函數 2;
新函數 2 以 3 為參數并且計算 f(g(x)),即 double(inc(3));
x=3 傳遞給 inc();
inc(3) 計算結果是 4;
double(4) 計算結果是 8;
最終返回結果是 8。
組合式軟件的過程可以用函數組合圖來表達,看下面代碼:
append = s1 => s2 => s1 + s2append('Hello, ')('world!')可以用圖來模擬表示:
λ 演算對軟件設計的影響是深遠的,直到大約 1980 年,計算機科學界很多有影響力的品牌,都是采用函數組合的方式來開發自己的軟件。Lisp 是 1958 年發明的,它深受 λ 演算的影響。直到今天,Lisp 是依舊廣為使用的第二大歷史悠久的語言。
我是通過 AutoLISP 知道的 Lisp,AutoLISP 是在最流行的電腦輔助設計(CAD)軟件——AutoCAD,中使用的腳本語言。AutoCAD 太流行了,使得其他所有的 CAD 應用幾乎都支持 AutoLISP 以保持其兼容性。Lisp 依然能夠在計算機科學課程中廣為使用有三個主要原因:
Lisp 非常簡單,基本上可以在一天之內學習完它的基本語法和語義;
Lisp 基本上全部是函數組合,函數組合來做應用架構的方式非常優雅;
我所知道的最好的計算機科學課本使用Lisp:計算機程序的結構和解釋
組合式軟件的沒落
在 1970 到 1980 年期間,軟件開發的方式開始發生變化,簡單的組合式開發不再受寵。出現了面向對象編程,它基于組件封裝和信息傳遞的思想,在當時是非常先進的。代碼通過繼承來實現復用,繼承關系是一種叫做 is-a 的關系。
函數式編程逐漸被邊緣化,被拋棄到學術界和非主流的場外。在 1990?—?2010 年期間對三種人形成了甜蜜的困擾,一種是編程極客,一種是大學教授,一種是逃離了 Java 思想強制灌輸的幸運的學生。而對于我們來講,這 30 年的軟件開發有一點噩夢般的感覺,黑暗的年代。
組合式編程的重新崛起
2010 年左右,有個巨大的變化:JavaScript 爆發了。在 2006 年以前,JavaScript 一直被認為是一種玩具式的編程語言,可以在瀏覽器中做一些很可愛的動畫,但是在這背后隱藏著潛力巨大的特點,即 λ 演算的重要特征。人們開始逐漸在私下里談論“函數式編程”。
到 2015 年,用函數組合來開發軟件重新開始流行起來。為了簡化使用,JavaScript 規范也做了 10 年以來的首次重大升級,增加了箭頭函數。箭頭函數使創建和使用函數、柯里化和 λ 演算變得很容易。
箭頭函數對于 JavaScript 函數式編程的爆發起到了推動劑的作用。現在很少看到那種不用函數式編程的大型應用了。
組合的方式可以簡潔清晰地描述軟件的行為,把一些小的、確定性的函數組合成大的組件,進而形成軟件,這樣的軟件很容易組織、理解、調試、擴展、測試和維護。
在讀接下來文章的時候,希望你能通過例子自己動手做實驗。回想一下當自己還是的孩子的時候,把一些東西拆開,自己再學著組裝、拼接。重新找回童年探索事物的感覺,希望你能享受這個過程。
如果本文對你有幫助,歡迎關注我的專欄-前端大哈,定期發布高質量前端文章。
我最近正在寫一本《React.js 小書》,對 React.js 感興趣的童鞋,歡迎指點。
總結
以上是生活随笔為你收集整理的函数式编程的兴衰与当前之崛起的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: lol云顶之弈怎么投降 云顶之弈投降技巧
- 下一篇: rtmp/rtsp/hls公网测试地址