Common Lisp语言快速入门
zhezhelin
Common Lisp語言快速入門
?
Lisp是軟件領域的分裂力量。一方面,Lisp愛好者誓言Lisp比軟件領域內的其它語言都更加快捷、整潔和強大;而反對者則辯稱,不可靠的執行和庫支持不足使得開發者難以在其中編寫任何真正的軟件。事實上,他們都有各自的道理。
第一版Lisp于大約50年前推出,這使得它和FORTRAN一樣,成為現在仍在使用的最古老的編程語言之一。可以證明,它擁有(它們將會擁有)最 龐大的特性列表,它也是第一種包括一整套今天我們全都認為是標準語言特性的語言,如垃圾收集、遞歸、函數作為對象、甚至是普通的if-then-else 子句。同時,人們也認為它是一款優秀的教學語言:MIT使用方案、Lisp衍生物,傳授它們的介紹性編程類。
我們將一起學習最強大和項目就緒的Lisp版本:Common Lisp,使其正常運行,并了解一些Lisp應用。
為何選擇Lisp?
- 代碼和數據并無差異——在Lisp中,代碼只是一個函數對象列表。源代碼和數據源之間不存在區別,允許Lisp把它的內在呈現給編譯器、注釋器和程序員。這允許你方便地本地讀入和評估代碼,甚至可以允許你使用宏。
- 宏——定義和重新定義任何語言元素。不喜歡條件、或循環或函數的運行方式嗎?好,你可以定義自己的注釋。如果你在代碼中多次執行某個特定的任務,把那個特性添加到語言中不是更加方便嗎?應用Lisp,你可以實現上述功能。
- 速度——雖然在許多情況下Common Lisp不如C或OCaml這類速度巨人快捷,但它在一系列測試中表現良好,特別是在執行一小段程序的情況下。了解一些基本的編譯器知識,你就能夠編寫出處理列表和大型數字的代碼,在執行速度和內存使用方面都要優于其它語言。
- 簡化——Lisp的一切功能都基于一些基本的理念——一旦你了解那些理念,你就幾乎能夠處理任何問題。Lisp程序員常常自夸說,僅僅用幾百行代碼,你就能在幾乎任何語言(如C++或Haskell)中執行一個Lisp注釋器。
- 靈活——以你喜歡的任何方式編寫代碼。更喜歡功能性的編程方法嗎?沒問題!想要完全反復編程嗎?草草寫下幾個快速的宏就可以完成任務。你可以用最方便最高效的方式編寫程序,而且這些程序都能良好地運行。
好,行了!我購買了Lisp,我如何進行安裝呢?
這是棘手的問題。不像是Python或C#一樣,Common Lisp沒有標準執行——該語言由一個規范,而不是執行來定義。Common Lisp也沒有C語言的優勢:在每一個平臺上都是一種支配性的執行或流行的執行。每個版本都應執行上述標準,但有一些細節要由編譯器或注釋器來處理,這使 得每個執行都稍有不同。
你可以使用幾種選項——在本文中我使用CLISP,它在Windows、Linux和Mac(僅PPC)上運行良好。如果你使用英特爾Mac,則必須使用其它執行,如Allegro Common Lisp或SBCL。對于這篇快速入門中的簡單例子,你使用哪個執行都不要緊。
使用Lispbox可 以快速安裝Common Lisp系統,Lispbox為你提供一個Common Lisp執行、Emacs和SLIME——Emacs高級Lisp整合模式,許多Lisp程序員會告訴你說,它是使用Lisp的唯一方法。如果你并非 Emacs用戶(我本人也和你一樣),不要擔心,它并非必要條件,只是使得編寫Common Lisp程序更加簡便。
安裝過程因平臺而異,在Windows中你只能運行安裝程序,多數Linux軟件包管理器提供安裝包等。選擇一個執行并遵循安裝指令即可。打開REPL(交互式提示符)之后再返回這里,我們繼續往后講。
REPL
REPL代表“閱讀-評估-打印-循環”(Read-Evaluate-Print-Loop),它簡單表示注釋器的一個交互式提示符。你可以從這 里輸出一些簡單的Lisp代碼。如果你使用另一種注釋器提示符,你可以在這里使用提示符作為計算器輸出一些基本的數學表達式——但它不能正常運行。在 CLISP中輸入5*2不會返回任何有意義的結果:
[1]> 5 * 2
5
[2]>
5
[3]>
2
Lisp并非以那種方式運行,運算符,如“+”不是在數字之間,而是在數字前面,就好像它們是函數名稱一樣。因此,如果你想將REPL當作計算器使用,你必須輸入:
[1]> (* 5 2)
10
[2]> (+ 1 2 3 4)
10
[3]> (+ (* 5 2) (* 10 3) (/ 100 4))
65
對你來說,理解這種用法可能更難一些,但它擁有一些優勢:它便于編譯器解析、它對所有函數和運算符都一樣、它讓你給函數添加盡可能多的自變量——例如,在上面的第二個例子中,你可以任意擴充加數,使得加法函數和總計函數完全一樣。
另外你會注意到,函數名在括號內,而不像許多其它語言一樣函數名在括號以外。這表示你要寫(函數自變量)而不是函數(自變量)。
每個Lisp表達式會返回一個值,一個函數總是返回最后一個表達式的結果——即使是NIL,NULL在Java或C++中的對等值也是這樣。因此在Lisp中顯示“Hello World”相當簡單:
[3]> "Hello World"
"Hello World"
如果你希望在屏幕上打印一些內容,并返回其它內容,你應該使用打印函數:
[4]> (print "Hello World")
"Hello World"
"Hello World"
這個字符串顯示兩次,一個是打印結果,一個是函數返回的結果。
Lisp表示LIST Processor(列表處理器),Lisp中的幾乎所有內容都以列表的形式存在,因此有時你必須處理列表。定義列表非常容易:
[5]> (list 1 2 3 4 5)
(1 2 3 4 5)
[6]> '(1 2 3 4 5)
(1 2 3 4 5)
第二種定義方法叫做引用,除定義簡單的列表外,它還有更多用途,不過我們必須在后面的另一篇文章中討論那個主題。
控制流程
Lisp擁有全部標準控制流程方法。定義一個重復一個值的簡單循環相當容易:
[7]> (dotimes (i 10) (print i))0
1
2
3
4
5
6
7
8
9
NIL
同樣,重復一個列表也很簡單:
[8]> (dolist (i '(0 1 2 3 4 5 6 7 8 9)) (print i))
0
1
2
3
4
5
6
7
8
9
NIL
以上兩個函數都是DO函數的特殊版本,它就像在其它語言中組合使用while和for函數一樣。它由三個部分組成:循環變更定義、終止條件和語句主體:
[9]> (do ((i 0 (+ 1 i))) ((> i 10)) (print i))
0
1
2
3
4
5
6
7
8
9
10
NIL
在這個例子中,變更定義部分為((i 0 (+ 1 i))),它定義變量i為0,并在每次循環時調用函數(+ 1 0)。終止條件為((> i 10)),表示在i大于10時函數終止運行。最后主體部分打印i的值。
Lisp中也有條件函數,最基本的條件函數為if函數:
[10]> (if (> 10 20) (print "Hello") (print "World"))
"World"
"World"
if函數由三部分組成:條件、then語句和else語句。如果條件為真,則執行then語句,否則就執行else語句。
你可能已經注意到,到現在為止我們僅使用了單個的語句——但如果你需要把幾個語句連接在一起,那該怎么辦呢?在Lisp中,要將幾個語句連接起來,你需要使用progn這個特殊的控制流程函數:
[11]> (progn (print "Hello") (print "World"))
"Hello"
"World"
"World"
例如,上例允許你在條件函數和循環中使用幾個語句。
好了,以上內容已足以讓你初步認識Common Lisp語言:通過你了解的內容,你可以編寫出一些微型程序,對Lisp語言進行測試。請密切關注本系列的下一篇文章,到時我們將介紹Lisp獨特的列表處理機制。
總結
以上是生活随笔為你收集整理的Common Lisp语言快速入门的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 试了下CommonLisp的WEB开发
- 下一篇: Windows环境下学习Lisp和Sch