如何看待編程語言越來越大的趨勢?

最近在學編程語言歷史,發現編程語言越來越大:

很早的Algol 60,語言的reference manual只有16頁,可以弄進一個小冊子帶著,但是一個structured programming language該有的都基本上齊了(除了沒有record, module,因為那時候還沒發明出來)

如果完全忽略實用性,去掉數字,lisp的最簡版是7條定理,再簡化一下我們甚至可以用各種Lambda Calculus/Combinator,更簡短。

70年代,CPL,Algol68,都變得有100,200多頁,導致CPL時隔7年才試下出來,Algol68則標準內容越加越多,導致多次跳票,最後Tony Hoare寫出來&來批判這種狀況。

但是現在,各種語言都是500頁,1000頁,甚至更多(squeak有2000個class)。

幾個參考角度:

0:語言為何變得越來越大了?

1:可不可能做出小而全的語言?

2:大的語言有沒有/如何解決學習,實現,研究,修改更困難的問題?(比如說,模塊化各部分,macro,提供語言相關API(language server),擁有一個更小的核心等等)這些解決方法有沒有不足之處?


看到這個題目我馬上想起了 Guy Steele 的 Growing A Language.

這個問題對於我這個從 Lisp 入坑 FP 的來說也有想過, 誰不想幻想過像 Lisp 一樣從幾條簡單規則出發去建立一個可以建模整個世界的龐大體系?

當初看到 Scheme R5RS 開篇就說:

Programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary.

說得好有道理, 估計沒有人不贊同的吧...

但是不得不承認的是我們實際經常使用的語言是越來越大了.

借用 為什麼 Haskell 始終沒法流行呢? 里提到的兩個觀點:

- New Language tend to look like old language

- Every Language Fixes Something

通常的通用語言都是建立在之前的語言身上, 加上點自己認為正確的東西然後再在這些東西上面結構更多的抽象, 而且為了保持向後兼容性, 被抄的語言自身發展的時候不會砍東西, 反而為了保命會把其他語言的改進抄回去, 這種趨勢下去當然是會越來越大了.

另外一方面, 隨著幾大語言實現 Backend (JVM, JS, BEAM)的成熟, 構建在其上面的語言肯定會兼容不少之前的特性, 這就引入了路徑依賴, 想砍 feature 的時候當然會考慮 target 平台上的 adoption 問題, 所以這方面都是做加法而不是減法. LLVM 跟往後的 WASM 會不會好一點點?

換一個角度, 從 Spec厚度角度來看. Spec 一般包含語法, 語義, 數據類型/抽象, 標準庫, 甚至還有一些實現細節等等等. 其實占篇幅最多的是標準庫部分, 變化比較大的也是這一部分, C++每一版加東西很多都加在庫里. 如果把標準庫砍掉, 單純是只是語言的話, 就像其他答案提到所謂的"在語言層解決".

The point of a standard library is not that it is good (in the early days, it often is not), but that it removes the need to make a choice.

via https://twitter.com/ezyang/status/869726749516591104

換句話說這樣其實更加慘, 各種實現, 各種 API 會各自為政, 委員會坐下來就是討論這些事(所謂Design By Committee) Scheme 算是個例子: R5RS 沒有定標準庫各種東西, 各種實現雖然協定好了SRFI, 但是都可以選擇性實現, 能用庫得看實現臉色, 到R7RS就被拆成 Small 跟 Large, 後者給 Scheme 加多點庫特性之類的讓 Scheme 可以更加通用, 但是現在 Small 出了好多年還沒有啥消息. 但是有了標準庫也不能解決, 做同一件事情上各種庫群魔亂舞的事, 總會有人嫌標準庫 API 設計得爛, 性能差, 更新慢, Go 算是這方面一個正面的例子, 單純標準庫就可以搞上生產環境.

所以語言和標準庫的關係有點像 Facade pattern, 各種庫作為子系統由語言提供介面. 如果庫在生長需要語言來支持的時候, 語言也會跟著生長, 這樣語言還是會慢慢變大起來.

至於一開始沒有 Spec 只有實現的語言(後面都各種補漏), 經典的如 Perl, PHP, Ruby, Python 語言就都是野蠻生長了, 永遠不會有回"做小"的趨勢.

至於

&> 大的語言有沒有/如何解決學習,實現,研究,修改更困難的問題?

在實現修改上答案顯然是有的:

All problems in computer science can be solved by another level of indirection.

學究如 Haskell (就不說be5說的 Coq 這種了), 就有 Core, 而且 Core 很穩定, GHC 加了好多 extension 都是沒啥變化, 當然到 Dependent type 不得不改了. 又或者 Scala 返工搞的 Dot: The Essence of Scala 和 Dotty. 這是語義,類型層面的最小化.

實現上, 即便有個 LLVM 和 WASM, 但好像還是不夠?

Swift 就有 Swift Intermediate Language: apple/swift

Scala 有 TASTY https://docs.google.com/document/d/1h3KUMxsSSjyze05VecJGQ5H2yh7fNADtIf3chD3_wr0/edit

實用語言的加上各種東西變大是不可避免的, 你看"新一代"在 Github 上開發的語言: Rust, Elixir, .... 各種 Contributor 給語言各方面添磚加瓦, 像一個"庫"那樣子在迭代, 或許這就是未來"Programming Language Design" 的樣貌

至於"可不可能做出小而全的語言", 就像 Hoare 所說:

There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.

同時做到orthogonal, composable已經好難了,我也沒太多想法, 翻到兩篇相關的 Paper:

Languages as Libraries

On the Expressive Power of Programming Languages

這問題還是有點大, 先想到那麼多 (


0. 因為人類的慾望是無止境的……

1. Lua、Scheme 這種可以看作示例,基本上動態定型語言的特性都包含了(或者可以整出來)

2. 分離啊,像 Scheme 就開始拆 R7RS Small 和 R7RS Large 了。

對於更加複雜(而且是內稟複雜)的語言還可以分層。像 Coq 和 Epigram 這種給數學家設計的 Proof Assistant 特性極多,但又要保證邏輯的正確性,怎麼辦呢?分層,把上層的語言 Elaborate 到一個很小的 core,然後你保證 core 正確就可以了。


one語言?不存在的。

「One語言」是不存在的-backup

0,語言肯定會變的越來越複雜的,因為要與時俱進嘛。一方面是適應新的底層機器,一方面是迎合大部分人的需求。需求不一定合理,但是如果是大眾化需求,總是不實現人們就會去找更好的替代品。

1,小而全,難。小是指語言核心小吧?全是指滿足各種需求?那小而全就要提供給用戶自己實現dsl的特性。考慮到大部分用戶用明白都難。自己實現真的實用的dsl就更難了。lisp發展了這麼多年還是小眾。我預測還會小眾下去。當然小眾不一定是壞事。

我好想跑偏了,就用一種簡單語言去實現複雜系統行不行?當然行,但是想成為分分鐘幾十行高質量彙編/C/C++/Haskell/邏輯公式代碼的人實在是太難了。"工業"語言的各種複雜特性的初衷就是讓用戶只用寫冰山一角就好,把難搞的複雜的東西隱藏起來,當然了,naive用戶撞上去沉船是後話。

2,大語言的學習問題並不存在。別說複雜語言了,我敢說即便是學scheme的,能知道"`@,.都是啥也得花段時間。

學語言常見學法:看書抄書試例子,新語言刷題,新語言寫項目,看新語言的優秀項目源碼。

然後我們學到了什麼語言呢?我們能記住的,理解的,認為合理的語言子集。所以語言再大,學到的也是相對小的。

這就是為啥發論文經常用Haskell子集,因為這就夠用了?

最後來總結一下設計一門語言需要哪些前置課程吧:(反正我都不會,哈哈哈哈)

1,數理邏輯,程序語言設計理論,類型論,證明論,範疇論 (語言)

2,計算機組成原理,分散式計算 : 了解多cpu/gpu並行,了解分散式計算,了解多級緩存,了解simd,了解流水線並行 。 (機器)

了解這些課程以後就會發現一堆嗷嗷待哺的語言需求。在語言層面資瓷這些需求都說的過去。

怎麼把這些東西都實現掉,還能互不干擾。

充分利用機器,不損失太多性能,還能保證安全,還能容易達到優雅,還能寫出real world的東西。

小而美的語言真的能都照顧到這些么。。。

粗鄙之語,請大佬指教。


語言的核心是要解決通用計算問題,因此可以做到簡潔正交。但實際使用的過程中需要解決形形色色的領域特定問題,甚至還要解決程序編寫者本身帶來的問題。因此,語言越來越臃腫。別的不說,看看cpp11以來引入的新特性有多少是在填特定問題的坑。。。


我覺得這個問題還有一個問題,就是目前的編程語言是給人設計的,很多糖也好,特性也好,都是為了彌補人的缺陷。然而,現在有另一支,AI的崛起,是不是會產生一些為AI設計的語言呢?AI顯然會比人在某些方面的缺陷要少,也許能有更簡潔和小而美的語言產生。

AI來寫程序,或者程序來寫程序,應該可以讓軟體的開發的抽象層級更高,例如實現某一個功能,最後簡化出A-B-C的路徑,AI可以自己生成它知道的所有組合,然後自動跑一個benchmark,留下最健壯,最快的那一支,這應該就比人要靠譜。或許滿足這種需求的語言才能真正活下去,而剩下的語言,難免變成腳本語言。


0.我覺得抽象層級多了,封裝東西多了,糖多了,library就大了,為了GC可能還得加運行時/VM

1.比如說Lua

2.比如說C++


明明lib可以解決的問題偏要放在語言層面解決,編程語言不僅是人用,有些程序也輸出程序啊,你搞那麼複雜┗|`O′|┛


我覺得核心的東西變的並不多,只是成熟,穩定的模式、工具被不斷增加進語言本身中,封裝底層,提升抽象層次,降低使用者的負擔和門檻,提高開發效率。


學科體系越來越龐大,不再像剛出現的時候一個人就能窮盡,越來越高層次上的抽象變成了必然的趨勢,語言自然就變的龐大了


從汽車行業來說 該問題和 手動擋 自動擋一樣

從生活角度上來說 想獲得越簡單 就越複雜

從經濟角度上說 公共建設提供局部就業機會 必然會以其他局部就業機會和消費的犧牲為代價

如果非要評價

這是好事 抽象 隔離 封裝 模塊化 讓大多數人的編程更注意業務 少部分人做優化就好了 精英永遠是少數。

而且現在性能都不是大問題了 編程語言也面臨「銷售」問題不是


我覺得是因為一條最基本的人性:

懶,並且越來越懶


以前的開發工作基本上都是面向計算機的,現在的開發解決的問題越來越偏向某個特定領域。


參考MIT不教SICP。我覺得是同一個原因。


實際上,計算機語言最終對應CPU的指令。現在計算機流行RISC( Reduced Instruction Set Computer )架構,稱為 精簡指令集計算機,顧名思義就是指令越來越少。 你如果採用彙編語言編程,相對於過去的CISC複雜指令集,RISC已經非常簡單了。但是完全利用彙編語言完成一種複雜的程序功能,無異於重新創造輪子,這要相當於重複幾千年人類文明。所以編程語言會越來越大,這樣才能使計算機更高效的運行,充分發揮程序員的聰明才智。


語言小了,程序就大了


推薦閱讀:

怎樣理解 Continuation-passing style?
如何用Haskell實現面向對象編程?
怎樣理解 Partial Evaluation?
請問大家了解函數式語言編譯器的實現技術嘛?
為什麼lambda演算中,函數在定義上只允許一個參數,而有時卻又會有多個參數的寫法呢?

TAG:編程語言 | 函數式編程 | 編程語言理論 |