從過去5年編程語言的演化看未來趨勢
Fogus在這篇帖子里介紹了過去5年間涌現出來的一些新的編程語言,就如作者本人所說,你并不需要也不可能掌握所有這些語言,但是花點時間了解下它們,或許你就會從中發現未來編程語言的演進趨勢,原文介紹了14種語言(當然不止這些),由于篇幅太長,我將分兩部分發布這篇文章:
推薦:51CTO編程語言排行榜
前些天我編譯了一個Perlis(譯者注:Alan Perlis,第一屆圖靈獎得主)語言列表,目的就是為了向大家展示主流編程語言之外的廣闊天地,這些語言只是為了拓展你的視野,就藝術性和實現上的技巧性而言,并沒有什么過人之處。在今天這篇帖子里,我會向大家介紹一些相對較新的編程語言(讓我們限定在過去5年之內),主要目的是展示這些語言中的一些有趣的特性,以及當前人們對舊有編程語言的認識,和對下一代語言發展方向的思考和探索,下面所列的這些語言有些可能已經停止開發了,但是在某種程度上它們依然代表了人們對于“新一代編程語言”的思考與探索,記住,這有時候并不意味著就是“創新”。
同我的Perlis列表不同,下面所列的這些語言我并沒有花太多的時間去了解,所以,如果有錯誤還希望大家能夠批評指正,另外,以下排名不分先后。
Shen
發布時間: 2011, 作者: Dr. Mark Tarver
在我的Perlis列表里,我介紹了Qi這門語言,所以在這里介紹它的繼承者Shen就是理所當然的事情了,事實上,Shen和Qi的大部分(或者全部?)的特性都差不多:
* Lisp方言
* 可選靜態類型
* 帶保護的模式匹配
* 宏
* 交互式執行(Partial application)
* 函數回溯(backtracking)
* 內置Prolog
* 內置編譯器
盡管如此,Shen實際上是Qi的進化版,Shen的很多點子都是繼承自Qi,但是同Qi不同,它最主要的目標是靶向性(targetability),這是什么意思呢?Qi主要是以Common Lisp作為它的宿主語言,并在這方面花了大量精力,盡管如此,Qi的實現實際上只使用了Common Lisp的一個非常小的子集,因此,Tarver博士決定繼承這個點子,并限定Shen只依賴一個叫做KI的最小化的Lisp語言核心,因此在理論上, 這讓Shen可以更容易的移植到其它宿主語言上,比如Javascript,Python,Clojure以及Common Lisp等等,“kernel Lisps”曾經激起過我的無限遐想,Shen算是在這方面的一個比較成熟的實踐。
下面是一個簡單的使用了嵌入Prolog的member函數:
- (defprolog member
- X [X | _] <--;
- X [_ | Y] <-- (member X Y);)
- (prolog? (member 1 [1 2 3]))
- /*=> true */
交互式執行(Partial application):
- (* 2)
- /*=> #
- ((* 2) 54)
- /*=> 108 */
下面這個函數用于計算第N個三角形數:
- (define triangle
- 0 -> 0
- N -> (+ N (triangle (- N 1))))
- (triangle 100)
- /*=> 5050 */
這是上面那個函數的帶類型限定的版本:
- (tc +) /* turn on type-checking */
- (define triangle
- {number --> number}
- 0 -> 0
- N -> (+ N (triangle (- N 1))))
- (triangle 5)
- /*=> 15 : number */
- (triangle a)
- /* type error */
我們可以將Shen看作是Lisp漫長,蜿蜒的歷史中的一個自然的進化,實際上許多現代語言只不過是從Lisp語言中吸收了其早在很多年之前就已經提出過的理念而已,因此,要說最令人激動語言,那仍然是Lisp本身。
更多資源:
* 官方網站
* 源碼
#p#
Agda 2
發布日期:2009,作者: Ulf Norel
我曾試著想要全身心的投入到Agda語言中,但是關于它,我卻不知從何說起,首先,Agda是一門純函數式,模式匹配,獨立類型的編程語言,并且,它還嘗試實現輔助證明(proof assistants)。在獨立類型的語言中,類型表達式可以包含一個程序表達式,因此,對類型的限定就只能通過函數語句或是值預測來解決,就實在是再遭不過了,Agda的類型語句和值語句是等價的(就是編程語句本身),這就意味著Agda的類型系統可以支持遠比靜態語言復雜的多的數據類型,比如,我們可以說這個函數只接受已經經過排序的列表類型(PDF),恩,讓我們看個例子吧:
下面是一個Agda類型系統的奇偶數編碼程序
- data Nat : Set where
- zero : Nat
- suc : Nat -> Nat
- fortyTwo : Nat
- fortyTwo = 42
- plus : Nat -> Nat -> Nat
- plus zero mm = m
- plus (suc n) m = suc (plus n m)
- mutual
- even : Nat -> Bool
- even zero = true
- even (suc n) = odd n
- odd : Nat -> Bool
- odd zero = false
- odd (suc n) = even n
上面的代碼定義了兩個數據類型 1) 自然數 2)偶數,當然,你也可以定義類型函數作為前置操作符:
- _+_ : Nat -> Nat -> Nat
- zero + mm = m
- suc n + m = suc (n + m)
目前為止我對Agda的了解也就這些了,但是如果有時間,我希望可以對它做進一步的了解。
更多資源:
* 介紹資源
* 源碼
#p#
Ioke
發布日期:2008,作者:Ola Bini
Ola Bini的Ioke語言就是為了回答這樣一個很簡單的問題:如果完全不用考慮性能,而只專注于表達性(expressivity),那么你會創造怎樣的一門語言出來?事實證明從Bini的PPT里你可以看到這門語言具有難以置信的可表達性(見下面鏈接),Ioke最有趣的一個特性就是它是一個支持宏的homoiconic語言(homoiconic指程序本身可以作為語言的一種數據結構來表示)。
- myfor = dsyntax(
- "takes a name, an enumerable, and a transforming expr
- and returns the result of transforming each entry in
- expression, with the current value of the enumerable
- bound to the name given as the first argument",
- [argName, enumerable, argCode]
- ''(`enumerable map(`argName, `argCode))
- )
- myfor(x, 1..5, x*2)
- ;=> [2,4,6,8,10]
另一個促使我學習Ioke的動力就是:
牛逼的人創造的東西總是值得學習的。
不斷將我們的能力推向邊緣是作為程序員的職責所在,而學習聰明人的創造則是做到這點最有效的方式。
更多資源:
* Ioke
* Ioke: a Folding Language (視頻)
* 源碼
* Macro types in Ioke – or: What is a dmacro?
#p#
Pure
發布日起: 2008, 作者: Albert Gräf
Pure也是一個基于term rewriting構建的函數式編程語言,Term rewriting有點像是我們在高中代數里用到的FOIL(一種拆解多項式的方法)方法:
- (x1 + y1) * (x2 + y2) =
- (x1 * x2) + // First
- (x1 * y2) + // Outer
- (y1 * x2) + // Inner
- (y1 * y2); // Last
上面的代碼展示了如何使用FOIL方法來對兩個多項式相乘進行變換,讓我們來看看Pure可以做什么:
- (x + 3) * (x + 5);
- //=> x*x+x*5+3*x+15
或許你認為答案應該是x^2 + 8*x + 15,但是因為我們沒有定義消除冗余的操作,所以結果會是下面的樣子:
- x*xx = x^2;
- (x + 3) * (x + 5);
- //=> x^2+x*5+3*x+15
這已經很接近了。
另一個更復雜的例子就是求解一個數的質因子:
- factor n = factor 2 n with
- factor k n = k : factor k (n div k) if n mod k == 0;
- = if n>1 then [n] else [] if k*k>n;
- = factor (k+1) n if k==2;
- = factor (k+2) n otherwise;
- end;
- factor 138;
- //=> [2,3,23]
要說在這篇帖子里最讓我佩服語言,就是屬Pure了。
更多資源
* 源碼
#p#
Go
發布時間: 2009,作者: Robert Griesemer, Rob Pike, and Ken Thompson
對于是否要在這篇貼子里介紹Go讓我糾結了很久,到目前為止,我對Go都有非常強的抵觸情緒,盡管如此,但是人們似乎覺得多一種系統級的編程語言選擇是件好事情,所以最終我還是決定拋棄個人偏見,將Go包含在內。
下面是一段用Go編寫的游程編碼(run-length encoding)程序:
- package main
- import (
- "fmt"
- "strings"
- )
- var order = 4
- var grain = "*"
- func main() {
- t := []string{grain + strings.Repeat(" ", len([]int(grain)))}
- for ; order > 0; order-- {
- sp := strings.Repeat(" ", len([]int(t[0]))/2)
- top := make([]string, len(t))
- for i, s := range t {
- top[i] = sp + s + sp
- t[i] += s
- }
- t = append(top, t...)
- }
- for _, r := range t {
- fmt.Println(r)
- }
- }
對于系統級編程,這個世界需要更多的選擇,而Go正是針對這個目標設計的。
更多資源
* 源碼
* 指南
#p#
Arc
發布日起:2008,作者:Paul Graham以及Robert Morris
很難相信Arc居然只是一個3年前才誕生的語言(根據發布日期),當然,我之所以覺得它古老,這和我花了無數時間閱讀Graham介紹Arc的帖子有關,在Arc發布之前,它曾讓人無比激動,但不幸的是,在它真正發布之后,對這個語言的評價基本上都處于失望和生氣之間,我也非常想要喜歡它,但是找來找去我還是沒能找到充足的理由說服自己,我覺得如果沒有Clojure,Racket或是Qi這樣的語言,那么我或許會愿意去嘗試下Arc,不過我必須得承認,Arc的核心理念“簡明就是力量”仍然深深的打動了我,除了語言本身(它的實現只部分遵從了這一原則),它的核心哲學依然足夠強壯,讓我們來看看Paul Graham在“Arc challenge”里的這段話吧:
假設要寫一個程序讓某個URL(比如,http://localhost:port/said)產生一個帶有輸入框和提交按鈕的頁面,然后當提交按鈕被按下時,這時應該有第二個頁面,這個頁面只包含一個簡單的鏈接“點這里”,當你點了這個鏈接之后,會出現第三個頁面,在這個頁面你會看到“你剛剛說的是:……”,這里的省略號就是你在第一個頁面所輸入的內容。
要實現上面描述的功能,下面是Arc的解決方式:
- (defop said req
- (aform [w/link (pr "you said: " (arg _ "foo"))
- (pr "click here")]
- (input "foo")
- (submit)))
學習Arc的一個額外的好處就是你可以順帶了解到Racket語言的神奇,好吧,我承認我作弊幫Racket做宣傳了。
更多資源
* Arc指南
* Arc核心
* Arc論壇
* Arc源碼
#p#
CoffeeScript
發布日期:2009,作者:Jeremy Ashkenas
我發現Jeremy Ashkenas絕對是個超級聰明的程序員,他的一些哲學與我不謀而合,另外值得注意的是,CoffeeScript是這篇帖子里介紹的這些語言中唯一一個我會在實際工作中使用的語言,它的語法實在是太干凈自由了,但是它最牛的地方(也有些人說這是最弱的)就是它只是對JS的非常淺的封裝,CoffeeScript實際上是對于Crockford(譯者注:JavaScript社區最知名的權威之一,JSON、JSLint、JSMin和ADSafe之父)的“Javascript: The Good Parts”一書的最好詮釋,并且還是以更優美的語法實現的。
CoffeeScript最有趣的一個特性就是它提供了一種非常輕量級的JSON語法:
- jsn =
- foo: 'a'
- bar: 'b'
- jsn.bar
- #=> 'b'
這讓下面這樣的對象語法變得更加容易:
- sanders =
- speed: 8
- juke: 10
- report: -> "#{@speed} and #{@juke}"
- sanders.report();
- #=> '8 and 10'
還有列表的實現:
- transpose = (matrix) ->
- (t[i] for t in matrix) for i of matrix[0]
- transpose [[1,2,3],[4,5,6]]
- //=> [[1,4],[2,5],[3,6]]
下面這點不知道該說好還是壞,CoffeeScript還提供了基于類支持:
- class Animal
- constructor: (voice) ->
- @voicevoice = voice
- speak: =>
- "#{@voice}!!"
- class Dog extends Animal
- constructor: ->
- super("ruff")
- d = new Dog
- d.speak()
- #=> 'ruff!!'
CoffeeScript并不是第一個基于Javascript的語言,但是它對JS的適配和支持是最完美的,并且實踐證明大多數人都可以接受這種方式,而同樣重要的是Coffeescript還解決了寄生語言如何與現有的JS庫和框架共存的問題。
更多資源:
* 官方網站
* 源碼
#p#
Potion
發布日期: 2009, 作者: _why the Lucky Stiff
曾經有個叫_why的家伙在ruby圈子里引起了一場不小的風波,作為一個神秘人,他對Ruby和編程的一些見解為他在ruby以及ruby之外的世界贏得了很高的聲譽,_why就是這樣一個神奇的開源貢獻者,在他的眾多開源項目中,有一個叫做Potion的項目,這個項目的目標是創造一個小巧且強大的新編程語言,Potion繼承了很多Io,Lua,OCaml以及Ruby的想法,并將它們匯集于一身:
- Person = class: /name, /age, /sex.
- Policeman = Person class (rank): /rankrank = rank.
- Policeman print = ():
- ("My name is ", /name, " and I'm a ", /rank, ".")
- join print.
- Policeman ("Constable") print
- # My name is nil and I'm a Constable.
不過讓我最感興趣的就是,Potion分離了數據和表達式的符號系統,當然我必須得承認這個語言并不是很富有創造性,這是因為作者將大部分精力都投入到了實現上,它的實現非常簡潔,只有大約6000行代碼,也就是說一般公司的年輕程序員(或者是像我這樣的老家伙)都可以在幾周之內完全理解整個語言的實現,閱讀代碼是個很好的學習方式,尤其是閱讀這樣出色的的代碼。
繼續了解
* 官方網站
* 源代碼
Mirah
發布日期: 2008, 作者: Charles Nutter
JRuby算是一個非常不錯的在JVM之上構建的語言了,但是就像其它許多的Java.next語言一樣,它也受到運行時問題的困擾,作為一個共生語言,要想提供一個強大且高效的開發和運行時體驗,共生語言需要提供一個可以在任何java運行時上部署的核心庫。如果我們將這個運行時限定在只支持一個輕量級的運行環境,那么這在實踐中就不是什么大問題。讓我們來看看Mirah,Mirah的目標(這是個很靠譜的目標)就是創造一個新的基于JVM的語言(語法主要借鑒Ruby),讓你可以得到動態語言的體驗,但又不需要增加任何額外的運行時庫。
- def reverse(s:string)
- StringBuilder.new(s).reverse
- end
- puts reverse('reversed')
初看起來,Mirah就是一個增加了類型聲明支持的JRuby,如果我不是這樣喜歡JRuby,或許我會希望Charles Nutter把他所有的時間都花在Mirah上。
繼續了解
* 官方網站
* 初始聲明
* 源碼
#p#
Scratch
發布日期: 2007, 作者: Mitchel Resnick
當我看到我5歲的兒子毫不費力的完成了對這些樂高機器人的編程時,我就在想著,或許應該有一種提供圖形化IDE的通用語言,當我發現Scratch時,我大吃了一驚,這個圖形化的語言居然和我想的如此接近,并且它和上面講的樂高機器人都是由MIT的一個小組開發的。
下面是Scratch版的“Hello,World”:

Scratch算是Smalltalk的一個近親,但是它的目標是以“玩樂式的體驗”幫助孩子學習必要的數學和編程技能——我非常贊同這個目標,Scratch雖然看起來和微軟的Kodu有點像,但是基于我玩樂高的體驗,我更喜歡Scratch一些。
更多資源
* 官方網站
* 源碼
ClojureScript
發布日期: 2011, 作者: Rich Hickey
ClojureScript是一個基于JavaScript之上的語言,它采用了大部分Clojure的語法,然后被編譯成Javascript,因為我本人就是ClojureScript的開發者,我對它的看法難免會有偏見,所以還是讓Brenton Ashworth來告訴你ClojureScript到底有多酷吧:
ClojureScript browser-connected REPL from Brenton Ashworth
這是個連我都被震住了的視頻。
繼續了解
* ClojureScript聲明
* 源碼
Clojure
發布日期: 2007, 作者: Rich Hickey
同上面一樣,我對Clojure的喜愛也不可避免的帶有偏見,所以我盡量少說一些,下面就是我對它的簡短評價:
不變性(Immutability)將會成為游戲規則的顛覆者
另外,下面是一個由Christophe Grand實現的生命游戲的Clojure版本:
- (defn neighbours [[x y]]
- (for [dx [-1 0 1] dy (if (zero? dx) [-1 1] [-1 0 1])]
- [(+ dx x) (+ dy y)]))
- (defn step [cells]
- (set (for [[loc n] (frequencies (mapcat neighbours cells))
- :when (or (= n 3) (and (= n 2) (cells loc)))]
- loc)))
- (def board #{[2 1] [2 2] [2 3]})
- (defn print-board [board w h]
- (doseq [x (range (inc w)) y (range (inc h))]
- (if (= y 0) (print "\n"))
- (print (if (board [x y]) "[X]" " . "))))
- (defn display-grids [grids w h]
- (doseq [board grids]
- (print-board board w h)
- (print "\n")))
再就是,我寫過一本關于Clojure的書。
更多資源
* 官方網站
* 源碼
#p#
OMeta
發布日期: 2009 (?), 作者: Alessandro Warth
最近幾年關于DSL的討論越來越多,大家的很大一部分注意力都被轉移到了這個話題上,盡管如此,如果有人曾經參與過DSL的設計或者實現,那么他應該會發現,現在的情況遠不能讓人滿意,問題就是你很難用一個通用語言實現一個既強大又健壯的DSL,造成這個問題的原因有很多,但最主要的問題就是,即使是使用那些具有很大的語法靈活性的語言,你也仍然很難保證你實現出來的DSL不會太過丑陋,當然,你可以做到,但是如果你想要實現一個理想的DSL,你會發現,你真的需要一套簡單的工具來幫你構建一個完整的語言解析器和運行時,關于這個,我都可以花上一天再寫個新帖了,但我還是先省省吧,讓我們回到主題,真的,DSL的世界需要這樣一種語言,它只是為你提供一套工具,讓你可以編寫獨立的DSL解析器,或是嵌入式的變體,沒錯,那就是OMeta。
就像JetBrain的元編程系統提供的那種非常容易理解且強大的工具集一樣,OMeta最大的優勢就在于它非常簡單,OMeta是基于語法表達式解析器(PEG)構建的,你可以輕松對它進行擴展來支持通用的數據結構。
更多資源
* 官方網站
Fortress
Fortress有點超出了這個貼的時間限制,因為在它公開發布之前,它已經在Sun內部被使用了多年,Fortress之所以引起我的關注,只是因為Guy Steele參與了這個項目,除了這一點,Fortress引人注目之處還在于它將精力放在了并行計算上,它的語法看起來更像是數學符號,并且支持對象-函數范式,comprehensions,traits, contracts以及靜態計量單位解析和分布式數據結構。
- for i←seq(1:m) do
- for j←seq(1:n) do
- print a[i,j]
- end
- end
上面的這個簡單的嵌套循環展示了Fortress的一個非常有趣的特性,那就是循環中的語句是并行執行的,Fortress對于并行采用了一個很堅決的做法,它沒有將并行作為語言的一個可選項,而是將它和語言本身緊密的結合在了一起,當然,除了這種隱式的并行,Fortress也支持顯式的并行計算。
更多資源
* 項目主頁
* 源碼
接下來?
最近又涌現了許多新的編程語言,但是我對這些語言的了解僅限于一條Tweet的長度:
* Dart
51CTO推薦專題:Google Dart新結構化編程語言
第一定理(譯者注:這里指作者前面說的一句話:當牛逼的人創造了某個東西,你應該學習之)
看起來為適配更多的運行時做了均衡
* Rust
看起來像是D語言的繼承者
第一定理
* Ceylon,不確定對于一個堅持追隨Java約定的團隊,這個語言為他們提供了什么
* Kotlin,基于IDE打造
* Newspeak,smalltalk+: FloatD的簡化版
* Perl6,鑒于我不是Perl程序員,所以我可以等
* Magpie
或許是最好的關于編程語言開發的“Blog"了
很不幸沒時間去看它的源代碼
由Dart團隊的一員開發
感謝Tracy Harms提醒
更少人知道的
下面這些語言是其他人推薦給我的,我對它們基本上一無所知:
* Felix 屬于ML系
* Wheeler 看起來真的很獨特,我會花點時間探索下
* Opa 下一代的Web語言
* Frege 又一個Java.next語言,Haskell系
* Cobra 帶給我合同
* Clay 另一個系統級編程語言,在我看來很干凈
寫完這篇文章,一個讓我驚奇的發現是,過去5年間我們對于數組編程【6】幾乎沒有取得什么進展,盡管如此,我懷疑可能還有有一些私有的項目沒被我發現,隨著時間的推移,我的感受就是,編程語言正在朝著衍生和進化的方向發展,而不是再從頭重新發明一種革命性的新語言,這并不一定就是件壞事情,因為計算機史上還有很多隱藏的很深的好點子等著我們去發掘。
本文是“Programming language development: the past 5 years”一文的上半部分,作者:Fogus,翻譯:yuanyiz
原文:http://heikezhi.com/2011/11/06/programming-language-development-the-past-5-years-part-1/
【編輯推薦】