跳至內容

Common Lisp

維基百科,自由的百科全書

這是本頁的一個歷史版本,由Jobinson99留言 | 貢獻2011年2月20日 (日) 00:48編輯。這可能和目前版本存在著巨大的差異。

通曆Common Lisp,縮寫為 CL(不要和縮寫同為CL的組合邏輯混淆),是歷Lisp的眾多方言之一,標準由ANSI X3.226-1994定義。它是為了標準化此前眾多的Lisp分支而開發的,它本身並不是一個具體的實現而是各個Lisp實現所遵循的規範。

相對於各種嵌入在特定產品中的語言易碼歷Emacs Lisp自動歷AutoLISP,通曆 是一個通用用途的程式語言。不像很多早期的歷,通曆同Scheme一樣,其中的變量是有作用域的。

通曆 是一個多重範式程式語言,這表現在:

  • 支持各種編程技術:過程編程函數編程物件導向的編程。
  • 動態數據類型,但是可以使用可選的類型聲明來提高效率和增強安全性。
  • 可以通過一些標準特性來擴展,例如 Lisp宏(程序自我進行的編譯時代碼重排 (compile-time code rearrangement accomplished by the program itself))和 閱讀器宏(賦予用戶自定義的保留字以特殊意義的符號擴展 (extension of syntax to give special meaning to characters reserved for users for this purpose))。

語法

通曆 是一種 歷; 它使用 S-表達式 來表示代碼和資料結構。 函數和宏調用以列表的形式寫出,列表的第一項是函數名,就像在這些例子中:

(+ 2 2)           ;  将 2 加上 2, 得 4
(setf p 3.1415)  ; 设定变量 "p" 等于 3.1415
; 定义一个函数用来计算一个数的平方:
(defun square (x) (* x x))
; 执行这个函数:
(square 3)        ; 返回 "9"

數據類型

通曆 擁有相當豐富的數據類型,比很多語言都要多。

純量類型

數字 類型包括整數分數浮點數,和複數。通曆 使用 大數(bignum) 來表示任意長度和精度的數值。分數類型精確地表示分數,這是很多語言都不具備的能力。 通曆 自動將數值轉換成適當的類型。

通曆 字符 類型並不僅僅是 ASCII 字符,這是因為 歷 在 ASCII 出現前就存在了。 一些現代的實現允許使用萬國碼Unicode字符。[1]

符號(Symbol)類型是 歷 語言共有的,而在其它語言中就較少見。一個符號是一個唯一的命名數據對象。與其它語言中的標識符(Identifier)類似,歷 中的符號可以用作變量名,但它們也是可以獨立使用的一種數據對象。一般來說,對一個符號求值時會得到以該符號為名的變量的值,但也有例外:形如:foo關鍵詞符號的值就是它本身,而符號TNIL則分別表示布爾真與布爾假。

資料結構

通曆 的順序類型包括表(lists),向量(vectors), 位向量(bit-vectors),和字符串(strings)。

同任何其他的 歷 一樣,通曆中的列表稱作conses,有時候叫做cons cells 或者 pairs。一個cons就是擁有兩個槽的資料結構,這兩個槽被稱作 carcdr

函數

在 通曆 里, 函數 是一種數據類型。 例如,可以寫出以一個函數作為參數的函數,同時函數的返回值也可以是函數。這就讓用函數描述非常通用的操作成為可能。

通曆 的庫很強的依賴這種高階函數。 例如,sort(排序)函數用一個 比較操作符 作為他的參數之一。這樣一來,這個函數就不但可以用來對任何類型的數據排序,還可以根據一個關鍵碼對資料結構排序。

(sort (list 5 2 6 3 1 4) #'>)
; Sorts the list using the > function as the comparison operator.
; Returns (6 5 4 3 2 1).
(sort (list '(9 a) '(3 b) '(4 c))
    #'(lambda (x y) (< (car x) (car y))))
; Sorts the list according to the first element (car) of each sub-list.
; Returns ((3 b) (4 c) (9 a)).

這一求值模型對於函數很簡單。當求值器遇到一式形如 (F A1 A2...),那麼名為 F 的符號被認為是如下之一:

  1. 一種特殊操作符(容易根據一個確定的列表檢查)
  2. 一個宏(macro)操作符(必須事先被定義)
  3. 函數名(默認),它可以是一個符號或者是一個以符號lambda開始的子式(sub-form)。

如果 F 是函數名,那麼參數 A1, A2,...,An 被從左到右依次求值,然後找到函數定義,並把這些值作為參數調用這個函數。

定義函數

defun 用來定義函數。 函數定義給出了函數名,參數名和函數體:

(defun square (x)
   (* x x))

函數定義中可以包括 「聲明」,它可以指示編譯器優化設置或參數的數據類型等。還可以在函數定義中包括「文檔字符串」(vdocstrings),Lisp 系統用它們形成交互式文檔:

(defun square (x)
   (declare (number x) (optimize (speed 3) (debug 0) (safety 1)))
   "Calculates the square of the number x."
   (* x x))

匿名函數用 lambda 表達式定義。Lisp 編程頻繁使用高階函數,以匿名函數作為其參數的作法十分有效。

還有一些有關於函數定義和函數操作的運算符。如,操作符 compile 可以用來重新編譯函數。(一些Lisp系統默認下在解釋器里運行函數,除非指示編譯它;其他Lisp系統在函數輸入時即被編譯。)

函數名位

函數的名位與數據變量的名字空間是分離的。這是 通曆 和Scheme程式語言的一個重要不同之處。 在函數名字空間定義名字的操作符包括 defun,flet,和 labels

要用函數名把函數作為參數傳給另一個函數,必須使用function特殊操作符,通常簡略為 #'。上文第一個 sort 的例子中,為了引用在函數名字空間名為 > 的函數,使用了代碼 #'>

Scheme程式語言 的求值模型更簡單些:因為只有一個名位,式(form)中所有位置都被求值(以任意順序)-- 不僅是參數。 所以以一種方言 (dialect) 寫就的代碼往往令熟悉其它方言程式設計師感到迷惑。例如,許多 CL 程式設計師喜歡使用描述性的變量名如 "list" 或 "string",在 Scheme 中這將導致問題,因為它們可能局部覆蓋了函數名字。

為函數提供分離的名位是否有益是 歷 社區不斷爭論的主題之一,常被稱為 「Lisp-1 與 Lisp-2 辯論」。這些名稱出現於Richard P. GabrielKent Pitman 1998 年的一篇論文,其中廣泛的比較了這兩種方法。 [2]

其他類型

Variable capture and shadowing

同其他Lisp的比較

實現

通曆 是由一份技術規範定義而不是被某一種具體實現定義(前者的例子有Ada語言C語言,後者有Perl語言)。 存在很多種實現,語言標準詳細闡明了可能導致合理歧義的內容。

另外,各種實現試圖引入庫包來提供標準沒有提及的功能。可移植的自由軟體庫提供了各種特性,Common-Lisp.netCommon Lisp Open Code Collection 項目。

通曆 設計為由增量編譯器實現。 優化編譯的標準聲明(例如內聯函數)已進入語言規範的計劃。 大多數歷實現將函數編譯成原生的機器語言。其他的編譯器編譯為比特碼,有損速度但是容易實現二進制代碼的可移植。由於Lisp提供了交互式的提示符以及函數增量式的依次編譯,很多人誤會為歷是純解釋語言。

一些基於Unix的實現,例如CLISP,可以作為腳本解釋器使用;因此,系統可以像調用Perl 或者Unix shell解釋器一樣透明的調用它。

實現的列表

免費的可重發布實現包括:

  • CMUCL,最初來自卡內基梅隆大學,現在作為自由軟體由一個志願者團隊維護。 CMUCL 使用一個快速的原生代碼編譯器。它運行於 x86上的LinuxBSD;Alpha上的Linux;以及 SolarisIRIXHP-UX 。參見 [3]
  • GNU CLISP,是一個bytecode編譯的實現。它可移植並運行在很多Unix和Unix風格的系統上(包括Mac OS X), 以及Microsoft Windows 和一些其他系統。
  • Steel Bank Common Lisp (SBCL),是 CMUCL 的一個分支。 "寬泛的說,SBCL 是CMUCL的可維護性加強版本。" [4] SBCL 運行的平台和 CMUCL 一樣,除了 HP/UX;另外,它運行於PowerPC上的Linux,SPARC,MIPS,和Mac OS X之上。 SBCL 不使用解釋器;所有的語句編譯為原生機器碼。
  • GNU Common Lisp (GCL), GNU項目的 Lisp 編譯器。GCL還不是完全兼容ANSI,但它仍然是一些大型項目所選擇的實現,包括數學工具 Maxima, AXIOM 和 ACL2。GCL 運行在 十一種架構的GNU/Linux 下,以及 Windows, Solaris, 和 FreeBSD
  • Embeddable Common Lisp (ECL),設計為可嵌入C語言應用中;
  • OpenMCL,Macintosh Common Lisp的開源分支。如同名字所示,OpenMCL is native to the Macintosh;運行於Mac OS X,Darwin,和PowerPC 上的 Linux 。
  • Movitz 實現了x86上的Lisp環境而不依賴任何OS。
  • Armed Bear Common Lisp 是一個運行在Java虛擬機上的Common Lisp實現。它包括了一個編譯器可以編譯Javabyte code,並允許Common Lisp調用Java庫。Armed Bear Common Lisp 是Armed Bear J Editor的一個組件,但它也能獨立使用。
  • Jatha 是一個Java庫,實現了Common Lisp的大部分子集。

商業實現在這裡Franz, Inc.Xanalys Corp.Digitool, Inc.Corman Technologies and Scieneer Pty Ltd.

應用

Common Lisp 被用於很多成功的商業應用中,最著名的(毫無疑問要歸功於Paul Graham的推廣)要數Yahoo! 商店的站點。其他值得一提的例子有:

  • Orbitz,以旅行書籍為主的站點
  • MiraiIzware LLC's fully integrated 2d/3d computer graphics content creation suite that features what is almost universally regarded as the best polygonal modeler in the industry, an advanced IK/FK and non-linear animation system (later popularized by such products as Sega's Animanium and Softimage XSI, respectively), and advanced 2d and 3d painting. It is used in major motion pictures(most famously in New Line Cinema's Lord of the Rings), video games and military simulations.
  • Piano,一個用Lisp寫的商業的航空期前期設計包以及與它的競爭對手的比較
  • Xanalys Corp.的調查軟體,被全球的警察,安全部門和防止詐騙服務部門採用
  • Genworks International的多用途說明語言(GDL),是一個基於CL的開發工具,用來創建基於web的工程,設計和商業應用

也有很多成功的開源應用用Common Lisp寫成,例如:

同樣,Common Lisp也被許多政府和非盈利組織採用。NASA中的例子有:

外部連結