本文最初發(fā)表于作者個人博客,經(jīng)原作者 Gabriel Gonzalez 授權,InfoQ 中文站翻譯并分享。 我花了不少時間思考這個問題:編程歷史的終結(jié)可能是什么樣子的。我所說的“歷史的終結(jié)”,就是編程范式不再有重大發(fā)展的時候。 對于編程的“命運”我很關心,因為我更愿意參與那些讓我們接近終極編程模式的開源項目。從我的經(jīng)驗來看,這類工作壽命更長,影響更大,有助于推動整個編程領域的發(fā)展。 那么,對于編程而言,歷史的終結(jié)會是怎樣的呢?是不是:
一些人將編程視為已經(jīng)解決的問題,并將所有新的語言和范式視為舊語言或范式的翻版。在他們看來,剩下的工作就是慢慢地優(yōu)化事物,排除錯誤,或者解決非技術性的問題(比如人事管理或者資金),從而完善我們的工藝。 這一觀點我個人并不認同,因為我相信,至少,函數(shù)式編程范式將逐漸取代面向?qū)ο蠛兔钍骄幊谭妒剑m然函數(shù)式編程未必就是終極編程范式)。
或許機器可以將我們的自然語言指令翻譯成代碼,從而減輕了我們準確表達意圖的負擔。或許一些足夠智能的、人工智能驅(qū)動的 IDE 可以為我們自動地完成大多數(shù)程序。 同樣,我也不相信這一觀點,而且我認為 Dijkstra 在他的文章《論“自然語言程序設計”的愚蠢性》(On the foolishness of 'natural language programming**' 老實說,我不能肯定什么是正確答案,但是我會給出我自己關于編程的歷史終結(jié)的猜測。 我的觀點是,編程的下一個邏輯步驟是分成兩個沒有重疊的編程領域:
具體地說,我預期編程語言在本質(zhì)上將發(fā)展成為更具數(shù)學特性的語言,讓用戶編寫的程序像純粹的數(shù)學表達式一樣表達其意圖。 舉例來說,考慮下列布爾邏輯“和”運算符和函數(shù)合成運算符的數(shù)學規(guī)范: True && x = x 這些數(shù)學規(guī)范也是可執(zhí)行的 Haskell 代碼(盡管使用了額外的括號來與主流函數(shù)語法相似)。Haskell 是編程語言的一個例子,它的代碼希望類似于純數(shù)學表達式和定義。 由于現(xiàn)實世界是混亂的,因此任何呈現(xiàn)這種理想化數(shù)學界面的語言都需要在幕后引入大量的復雜性,在這里,運行時構(gòu)建可以用來掩蓋這些“丑陋”的細節(jié)。 換言之,我預言編程的歷史終結(jié)將是連接純數(shù)學表達式和現(xiàn)實世界的接口。 請允許我舉幾個例子,說明這種將用戶空間(userland)代碼數(shù)學化的趨勢已經(jīng)開始顯現(xiàn):
手動內(nèi)存管理曾經(jīng)是大多數(shù)編程語言的“用戶空間”問題,但新語言的總體趨勢是自動內(nèi)存管理(Rust 除外)。以前,內(nèi)存管理是程序員必須關心的一個明顯的副作用,現(xiàn)在,把內(nèi)存管理下推到運行時(通過垃圾收集或其他方式),使編程語言更加純粹,使它們更接近于理想化的數(shù)學表達式。 事實上,Rust 是證明這一規(guī)則的例外,因為人們普遍認為 Rust 更適合于構(gòu)建運行時,而非用于意圖的高級規(guī)范。
函數(shù)式編程是向更傾向于數(shù)學化的編程方向邁進的一個重要步驟:
關于這一點,我在《為什么我更喜歡函數(shù)式編程》(Why I prefer functional programming)一文中詳細討論過。 但是,函數(shù)式編程并非自由的勝利。有效地支持高階函數(shù)和閉包并非易事(特別是對于編譯語言來說),這就是為什么那些較不復雜的語言實現(xiàn)通常更傾向于命令式而非函數(shù)式。
對于 Haskell 的評估模型,我一直認為“懶惰評估”并不適合推廣其優(yōu)點。但我更傾向于認為,Haskell 擁有“自動評估管理”(注:這一解釋與實際情況相差不大,因為 Haskell 標準只規(guī)定了一個非嚴格的評估策略。GHC 是懶惰的,但是 Haskell 這一預言標準并沒有要求懶惰實現(xiàn)。詳情請參閱《懶惰與不嚴格》(Lazy vs. non-strict?)。換句話說,程序員將表達式指定為依賴于計算的圖,而運行時則找出最有效的順序來減少圖。 這里還有一個例子,我們把過去用戶空間問題(評估順序)推進到了運行時。忽略評估順序可以讓我們用更數(shù)學的方法來指定事物,因為評估順序在數(shù)學上同樣是不相關的。 在研究上述趨勢時,出現(xiàn)了一種常見的模式:
你可能會想:在不遠的將來,還有哪些用戶空間問題可能會被推送到運行時問題上呢?我能想到的例子如下:
這次是如此的接近未來,以至于它已經(jīng)發(fā)生了(見:Nix 和 Dhall)。這兩種語言都為獲取代碼提供了內(nèi)置支持,而沒有使用獨立的包管理工具來處理帶外包。這一語言級別的支持允許程序嵌入外部代碼,就好像它是一個純粹的子表達式,更接近于數(shù)學化的理想。
這個問題需要更多的解釋:我認為,類型系統(tǒng)是一個邏輯結(jié)論,它把錯誤處理推入“運行時”(實際上是推到了類型檢查器而非運行時)。在 Dhall 語言中,這種想法得到了充分的體現(xiàn):Dhall 不能用來引發(fā)或捕捉錯誤的用戶空間支持,因為所有的錯誤都是類型錯誤。(注:這有點過于簡化,因為 Dhall 支持 Optional 值,你可以使用 unions 在 Dhall 中模擬錯誤,但是它們不常以這種方式出現(xiàn),而且通常 Dhall 代碼使用類型檢查器捕獲錯誤。Dhall 是一種完全函數(shù)式編程語言,它做了很多工作來防止運行時出錯,例如,禁止比較文本是否相等。另外,該語言在技術上依賴于類型,并且支持在類型檢查時測試任意代碼,以便靜態(tài)地捕捉錯誤。) 依賴類型 和 完全 函數(shù)式編程語言的發(fā)展使我們與把錯誤處理推到運行時的目標更加接近。
事實上,我感到驚訝的是,尚未完成對大量日志記錄的語言支持(或者,也許發(fā)生了,但是我沒有注意到)。在語言中,這似乎是一件可以實現(xiàn)的很普通的事情,特別是在性能不敏感的應用領域中。 很多語言已經(jīng)支持分析了,如果用戶愿意為日志花費性能預算,那么將分析支持轉(zhuǎn)變?yōu)槿罩局С挚雌饋聿⒉皇且粋€什么大的飛躍。 日志是典型的副作用之一,它是一種“丑陋”的細節(jié),“破壞”了本來是純粹的、數(shù)學的代碼。
面向服務的架構(gòu)是另一種傾向,它會阻礙純無副作用代碼的編寫。 我并不清楚面向服務的語言運行時是什么樣子,但是我認為,目前的“無服務器”解決方案并不是我心中所想的那樣。諸如 AWS Lambda 之類的東西還是太低級了,無法提升本質(zhì)上是數(shù)學化的代碼。舉例來說,如果編程過程中有任何部分需要使用獨立的工具來部署或管理無服務器的代碼,那么這與編寫純數(shù)學表達式大相徑庭。必須有與“無服務器代碼的 Nix 或 Dhall”類似的東西。 你可以批評我的預言,說它是不可證偽的??雌饋砦铱梢詫⒕幊讨械男逻M展解釋為屬于運行時構(gòu)建或數(shù)學表達式范疇。 正因為如此,我想強調(diào)預言中的一個關鍵支柱:運行時和數(shù)學表達式的劃分會隨著時間而變得更明顯。它是預言的實際內(nèi)容,我們可以從語言中推斷出一些證據(jù)。 當前,許多主流編程范式和工程組織混淆了這兩種職責,因此,你最終會發(fā)現(xiàn),人們編寫的軟件項目是操作邏輯(運行時問題)和“業(yè)務邏輯”(數(shù)學意圖)的混合體。 在我的預言中,工程領域?qū)碛芯幊陶Z言理論或編程語言工程經(jīng)驗的人產(chǎn)生強烈的需求。這些人將負責構(gòu)建專用語言和運行時,將盡可能多的操作問題抽象出來,以支持各自企業(yè)的純數(shù)學領域特定語言。這些語言將會被另一組人所使用,其目的是將人們的意圖轉(zhuǎn)化為數(shù)學表達式。 這個預言的一個結(jié)果就是,在不遠的將來,你會看到編程語言的“寒武紀大爆發(fā)”。當語言工程師把更多的操作問題推到運行時中時,當然,他們需要根據(jù)特定的目標或組織需求對運行時進行定制,而非嘗試編寫一種通用語言。換言之,隨著每種新語言適應其各自的利基市場,在語言運行時(和類型檢查器)中會出現(xiàn)明顯的碎片化現(xiàn)象。 雖然存在一些運行時碎片,但你在用戶空間代碼中看到與此相反的趨勢:用這些不同的語言編寫的程序?qū)㈤_始更接近于彼此,因為他們本質(zhì)上變得更數(shù)學化了。數(shù)學表達式在某種意義上將成為用戶空間代碼的可移植“通用語言”,尤其是當非數(shù)學問題被推到相應語言的運行時。 這種預言更容易被證偽。 原文鏈接: |
|