Common Lisp

Common Lisp

Common Lisp,縮寫為 CL(不要和縮寫同為CL的組合邏輯混淆),是Lisp的眾多方言之一,與Scheme合稱現代兩大Lisp方言,標準由ANSI X3.226-1994定義。它是為了標準化此前眾多的Lisp分支而開發的,導致其語言規範和標準長達千頁。要注意,它本身並不是一個具體的實現,而是各個Lisp實現所遵循的規範。它操作的數據是動態數據類型,但也可用的類型聲明來提高效率和增強安全性。

簡介


Common Lisp是一個現代的,多重範式的,高性能,可編譯的標準化ANSI編程語言。相對於各種嵌入在特定產品中的Lisp方言,例如Emacs Lisp 和 AutoLISP,Common Lisp 是一種通用用途的編程語言。不像很多早期的Lisp,Common Lisp同Scheme一樣,變數有作用域。
Common Lisp具有高度靈活性,對象化編程以及快速的框架能力提供優異的支持。同時它還提供強大的宏能力,使編程者在編碼時定製自己的應用,並給編程者提供了高度靈活的運行環境,可在運行時修改和調試程序。其多重範式語言特性還允許編程者選擇適當的方法和範式適應編寫的應用程序。

語法


Common Lisp 是一種 Lisp;它使用 前置標識表達式(前標式)來表示代碼和數據。函數(function)和宏(macro)也以前標式的形式寫出,前標式的第一項是函數名或者宏名,就像在這些例子中:
>(+ 2 2) ; 將 2 加上 2, 得 4
>(setf p 3.1415) ; 設定變數 "p" 等於 3.1415
; 定義一個函數用來計算一個數的平方:
>(defun square (x) (* x x))
; 執行這個函數:
>(square 3) ; 返回 "9"
當求值器遇到一式形如 (F A1 A2...),那麼名為 F 的符號被認為是如下之一:
• 一種特殊操作符(容易根據一個確定的列表檢查)
• 一個宏(macro)操作符(必須事先被定義)
• 函數名(默認),它可以是一個符號或者是一個以符號lambda開始的子式(sub-form)。
如果 F 是函數名,那麼參數 A1, A2,...,An 被從左到右依次求值,然後找到函數定義,並把這些值作為參數調用這個函數。如果F是特殊操作符,那麼A1,A2,...,An是否會被求值以及求值順序會由操作符決定,比如
>(if (oddp x) ; 在x是奇數時返回t,否則返回nil
(print "x是奇數")
(print "x是偶數")) ; 判斷x是奇數還是偶數,並給出顯示。
上述代碼在求值時會在求值if后先求值條件式(第一個參數),條件式求值結果為t,則求值第二個參數,否則不求值第二個參數,直接求值第三個參數。
宏則是可以讓用戶完全自定義求值規則,換句話說,寫一種新的語言。

特點


Common Lisp 是一個多重範式編程語言,這表現在:
支持各種編程技術:過程編程,函數編程和面向對象編程。
動態數據類型,但也可用類型聲明來提高效率和增強安全性。
可以通過一些標準特性來擴展,例如 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))。

詳情


Common Lisp 擁有豐富的數據類型。

數據類型

數字類型包括整數,分數,浮點數,和複數。Common Lisp 使用 bignum 來表示任意長度和精度的數值。分數類型精確地表示分數,這是很多語言都不具備的能力。 Common Lisp 自動將數值轉換成適當的類型。
Common Lisp 字元 類型並不僅僅是 ASCII 字元,這是因為 Lisp 在 ASCII 出現前就存在了。一些現代的實現默認使用Unicode字元。
內名(Symbol)類型是Lisp語言共有的,而在其它語言中就較少見。一個內名是一個數據對象的唯一命名。與其它語言中的標識符(Identifier)類似,Lisp中的內名可以用作變數名,但它們也是可以獨立使用的一種數據對象。一般來說,對一個內名求值時會得到以該內名為名的變數的值,但也有例外:形如:foo的關鍵詞內名的值就是它本身,而內名T和NIL則分別表示布爾邏輯真與布爾邏輯假。

數據結構

Common Lisp 的順序類型包括鏈表(lists),向量(vectors),位向量(bit-vectors),和字元串(strings)。
同任何其他的Lisp一樣,Common Lisp中的基本數據單位稱作 首。尾(conses,有時候叫做cons cells 或者 pairs)。一個 首。尾 就是擁有兩個槽的數據結構,這兩個槽被稱作 首(car)和 尾(cdr)。

函數

在 Common Lisp 里,函數 是一種數據類型。例如,可以寫出以一個函數作為參數的函數,同時函數的返回值也可以是函數--這種函數稱為高階函數。這就讓用函數描述非常通用的操作成為可能。
Common Lisp 的庫高度依賴這種高階函數。例如,sort(排序)函數用一個 比較操作符 作為他的參數之一。這樣一來,這個函數就不但可以用來對任何類型的數據排序,還可以根據一個關鍵碼對數據結構排序。
>(sort (list 5 2 6 3 1 4) #'>)
; 使用函數 >來排序,也就是按大小從大排到小排序
; 結果是 (6 5 4 3 2 1).
>(sort (list '(9 a) '(3 b) '(4 c))
#'(lambda (x y) (< (car x) (car y))))
; 根據子鏈表的第一個,按照從小到大排序
; 結果是 ((3 b) (4 c) (9 a)).
這一求值模型對於函數很簡單。

定義函數

宏 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系統在函數輸入時即被編譯。)

函數名字空間

函數的名字空間與數據變數的名字空間是分離的。這是 Common Lisp 和Scheme編程語言的一個重要不同之處。在函數名字空間定義名字的操作符包括 defun,flet,和 labels。
要用函數名把函數作為參數傳給另一個函數,必須使用function特殊操作符,通常簡略為 #'。上文第一個 sort 的例子中,為了引用在函數名字空間名為 > 的函數,使用了代碼 #'>。
Scheme編程語言的求值模型更簡單些:因為只有一個名字空間,式(form)中所有位置都被求值(以任意順序)-- 不僅是參數。所以以一種方言 (dialect) 寫就的代碼往往令熟悉其它方言程序員感到迷惑。例如,許多 CL 程序員喜歡使用描述性的變數名如 "list" 或 "string",在 Scheme 中這將導致問題,因為它們可能局部覆蓋了函數名字。
為函數提供分離的名字空間是否有益是 Lisp 社區不斷爭論的主題之一,常被稱為“Lisp-1 與 Lisp-2 辯論”。這些名稱出現於Richard P. Gabriel 和 Kent Pitman 1998 年的一篇論文,文中廣泛的比較了這兩種方法。

實現


Common Lisp 是由一份技術規範定義而不是被某一種具體實現定義(前者的例子有Ada語言和C語言,後者有Perl語言)。存在很多種實現,語言標準詳細闡明了可能導致合理歧義的內容。
另外,各種實現試圖引入庫包來提供標準沒有提及的功能。可移植的自由軟體庫提供了各種特性,Common-Lisp net 和 Common Lisp Open Code Collection 項目。
Common Lisp 設計為由增量編譯器實現。優化編譯的標準聲明(例如內聯函數)已進入語言規範的計劃。大多數Lisp實現將函數編譯成原生的機器語言。其他的編譯器編譯為通用二進位碼,雖有損軟體運行效率但通用性好。由於Lisp提供了互動式的提示符以及函數增量式的依次編譯,很多人誤會為Lisp是純解釋語言。
一些基於Unix的實現,例如CLISP,可以作為腳本解釋器使用;因此,系統可以像調用Perl 或者Unix shell解釋器一樣透明的調用它。

免費的可重發布實現:

• Steel Bank Common Lisp (SBCL),是 CMUCL 的一個分支。 "寬泛的說,SBCL 是CMUCL的可維護性加強版本。" SBCL 運行的平台和 CMUCL 一樣,除了 HP/UX;另外,它運行於PowerPC上的Linux,SPARC,MIPS,和Mac OS X之上。 SBCL 不使用解釋器;所有的語句編譯為原生機器碼。
• Clouzure Common Lisp (原名OpenMCL),Macintosh Common Lisp的開源分支。如同名字所示,OpenMCL is native to the Macintosh;運行於Mac OS X,Darwin,和PowerPC 上的 Linux。
• CMUCL,最初來自卡內基梅隆大學,現在作為自由軟體由一個志願者團隊維護。 CMUCL 使用一個快速的原生代碼編譯器。它運行於 x86上的Linux和BSD;Alpha上的Linux;以及 Solaris、 IRIX 和 HP-UX。參見
• GNU CLISP,是一個bytecode編譯的實現。它可移植並運行在很多Unix和Unix風格的系統上(包括Mac OS X),以及Microsoft Windows 和一些其他系統。
• GNU Common Lisp (GCL), GNU項目的 Lisp 編譯器。GCL還不是完全兼容ANSI,但它仍然是一些大型項目所選擇的實現,包括數學工具 Maxima, AXIOM 和 ACL2。GCL 運行在 十一種架構的GNU/Linux 下,以及 Windows, Solaris,和 FreeBSD
• Embeddable Common Lisp (ECL),設計為可嵌入C語言應用中;
• 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,以旅行書籍為主的站點
Mirai,Izware 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寫成,例如:
Applicative Common Lisp,a full-featured theorem prover for a subset of Common Lisp.
Maxima,a sophisticated computer algebra system。
Compo,a language allowing complex musical structures to be described in a natural way.
Lisa,a production-rule system to build "intelligent" software agents.
同樣,Common Lisp也被許多政府和非盈利組織採用。NASA中的例子有:
SPIKE,the Hubble Space Telescope planning and scheduling system.
Remote Agent,winner of the 1999 NASA Software of the Year Award.