Lisp的誕生

turingbooks發表於2011-08-26

  Common Lisp是1956年John McCarthy發明的Lisp語言的現代版本。Lisp在1956年被設計用於“符號資料處理” ,而Lisp這個名字本身就來源於其最擅長的工作:列表處理(LISt Processing)。從那時起,Lisp得到了長足的發展:Common Lisp很好地支援了一組常用的現代資料型別;將在第19章裡介紹的狀態系統提供了Java、Python和C++等語言的異常系統裡所沒有的充分靈活性;強大的物件導向程式設計支援;以及其他程式語言裡完全不存在的一些語言機制。這一切怎麼可能?地球上怎麼會進化出如此裝備精良的語言來?

  這麼說吧,McCarthy曾經是(現在也是)一個人工智慧(AI)研究者,他在該語言的最初版本里內建的很多特性使其成為了AI程式設計的絕佳語言。在AI繁榮昌盛的1980年代,Lisp始終是程式設計師們所偏愛的工具,廣泛用於編寫軟體來求解包括自動定理證明、規劃和排程以及計算機視覺在內的各種困難問題。這些問題都需要大量難於編寫的軟體;為了處理它們,AI程式設計師們需要一門強大的語言,而他們將Lisp發展成了這樣一門語言。另外,冷戰也起了積極的作用——五角大樓向國防部高等研究規劃局(DARPA)投入了大量資金,其中的相當一部分給了那些研究諸如大尺度戰場模擬、自動規劃以及自然語言介面等問題的人。這些人也在使用Lisp並且持續地推進它以滿足自身的需要。

  推動Lisp特性進化的動力也同樣推動了其他相關領域的發展——大型的AI問題無論如何編碼總是要吃掉大量的計算資源,而如果你按照摩爾定律倒推20年,你就可以想象80年代的計算資源是何等的貧乏了。Lisp工作者們不得不想盡辦法從他們的實現中擠出更多的效能來。現代Common Lisp實現就是這些早期工作的結晶,它們通常都帶有相當專業的可產生原生機器碼的編譯器。感謝摩爾定律,今天我們從任何純解釋型的語言裡也能獲得可接受的效能了,效能對於Common Lisp來說再也不是問題了。不過,讀者在第32章裡仍然可以看到,通過使用適當的(可選)變數宣告,一個好的Lisp編譯器所生成的機器碼,完全可以跟C編譯器的成果相媲美。

  1980年代也是Lisp機的年代,當時好幾家公司(最著名的是Symbolics)都在生產可以在晶片上直接執行Lisp的計算機系統。Lisp因此成了系統程式語言,被廣泛用於編寫作業系統、編輯器、編譯器,以及Lisp機上的大量其他軟體。

  事實上,到了1980年代早期,幾家AI實驗室和Lisp機廠商都提供了他們自己的Lisp實現,眾多的Lisp系統和方言讓DARPA開始擔心Lisp社群可能走向分裂。為了應對這些擔憂,一個由Lisp黑客組成的草根組織於1981年成立,旨在集既有Lisp方言之所長,定義一種新的稱為Common Lisp的標準化Lisp語言。最後他們的工作成果被記錄在Guy Steele的《Common Lisp: the Language》(CLtL)一書裡,該書相當於Lisp的聖經。

  到1986年的時候,首批Common Lisp實現誕生了,它們是在Common Lisp試圖取代的那些方言的基礎上寫成的。1996年,美國國家標準化組織(ANSI)釋出了一個建立在CLtL之上並加以擴充套件的Common Lisp標準,其中增加了一些主要的新特性,包括CLOS和狀態系統。但事情還沒結束:跟此前的CLtL一樣,ANSI標準有意為語言實現者保留了一定空間以試驗各種最佳的工作方式。一個完整的Lisp實現將帶有豐富的執行時環境,並提供GUI介面、多執行緒控制和TCP/IP套介面等。今天的Common Lisp則進化得更像其他的開源語言——使用者編寫他們所需要的庫並開放給其他人。在過去的幾年裡,開源Lisp庫領域尤為活躍。

  所以,一方面Lisp是電腦科學領域的“經典語言”之一,其建構在經過時間考驗的各種思想之上。 另一方面,它完全是一門現代的通用語言,其設計反映了儘可能高效和可靠地求解實際問題的實用主義觀點。Lisp“經典”遺產的唯一缺點是許多人仍然生活在片面的Lisp背景之下——他們可能只是在McCarthy發明Lisp以來的近半個世紀中某些特定時刻接觸到了這門語言的某些方面。如果有人告訴你Lisp只能被解釋執行,因此會很慢,或者你不得不用遞迴來幹每件事,那麼一定要問問他們究竟在談論哪個Lisp方言,以及他們是否是在遠古時代學到這些東西的。

  但是我曾經學過Lisp,不過跟你所描述的不太一樣

  如果你以前用過Lisp,你對“Lisp”的認識很可能對學習Common Lisp沒什麼幫助。儘管Common Lisp取代了大多數它所繼承下來的方言,但它並非僅存的Lisp方言,並且取決於你在何時何地認識了Lisp,你很有可能學的是某種其他方言。

  除了Common Lisp以外,另一種仍然有著活躍使用者群的通用Lisp方言是Scheme。Common Lisp從Scheme那裡吸收了一些重要的特性但從未試圖取代它。

  Scheme最早在M.I.T.被設計出來,然後很快被用作本科電腦科學課程的教學語言,它總是被定位成一種比Common Lisp更加優美但又不同的語言。特別是Scheme的設計者們將注意力集中在使其語言核心儘可能地小而簡單。這對作為教學語言來說非常有用,程式語言研究者們也很容易形式化地證明語言本身的有關命題。

  這樣設計的另一個好處是使得通過標準規範理解整個語言變得相對簡單。但是,這樣做帶來的問題是它缺失了許多在Common Lisp裡已經標準化了的特性。個別的Scheme實現者們可能以實現相關的方式提供了這些特性,但它們在標準中的缺失使得編寫可移植的Scheme程式碼比編寫可移植的Common Lisp程式碼更加困難。

  Scheme同樣強調函式式的程式設計風格並且比Common Lisp使用更多的遞迴。如果在大學裡學過Lisp並且感覺它只是一種沒有現實應用的學術語言的話,那你八成是學了Scheme。當然,說Scheme具有這樣的特徵並不是很公正,只不過同樣的說法用在Common Lisp身上更加不合適罷了,後者專門被設計成真實世界的工程語言而不是一種理論上的“純”語言。

  如果你學過Scheme,你也應該當心Scheme和Common Lisp之間的許多細微差別可能會絆你一跤。這些差別也是Common Lisp和Scheme社群的狂熱份子之間的一些長期宗教戰爭的導火索。日後隨著我們討論的深入我將指出其中最重要的那些差別。

  另外兩種仍然廣泛使用的Lisp方言是Elisp——Emacs編輯器的擴充套件語言,以及Autolisp——Autodesk的AutoCAD計算機輔助設計工具的擴充套件語言。儘管用Elisp和Autolisp可能已經寫出了超過任何其他方言的程式碼行數,但它們都不能用在各自的宿主應用程式之外,而且它們無論與Scheme還是Common Lisp相比都是相當過時的Lisp了。如果你曾經用過這些方言的一種,就需要做好準備,你可能要在Lisp時間機器裡向前跳躍幾十年了。


相關文章