|
Lisp是軟件領(lǐng)域的分裂力量。一方面,Lisp愛好者誓言Lisp比軟件領(lǐng)域內(nèi)的其它語(yǔ)言都更加快捷、整潔和強(qiáng)大;而反對(duì)者則辯稱,不可靠的執(zhí)行和庫(kù)支持不足使得開發(fā)者難以在其中編寫任何真正的軟件。事實(shí)上,他們都有各自的道理。 第一版Lisp于大約50年前推出,這使得它和FORTRAN一樣,成為現(xiàn)在仍在使用的最古老的編程語(yǔ)言之一。可以證明,它擁有(它們將會(huì)擁有)最 龐大的特性列表,它也是第一種包括一整套今天我們?nèi)颊J(rèn)為是標(biāo)準(zhǔn)語(yǔ)言特性的語(yǔ)言,如垃圾收集、遞歸、函數(shù)作為對(duì)象、甚至是普通的if-then-else 子句。同時(shí),人們也認(rèn)為它是一款優(yōu)秀的教學(xué)語(yǔ)言:MIT使用方案、Lisp衍生物,傳授它們的介紹性編程類。 我們將一起學(xué)習(xí)最強(qiáng)大和項(xiàng)目就緒的Lisp版本:Common Lisp,使其正常運(yùn)行,并了解一些Lisp應(yīng)用。 為何選擇Lisp?
好,行了!我購(gòu)買了Lisp,我如何進(jìn)行安裝呢? 這是棘手的問(wèn)題。不像是Python或C#一樣,Common Lisp沒(méi)有標(biāo)準(zhǔn)執(zhí)行——該語(yǔ)言由一個(gè)規(guī)范,而不是執(zhí)行來(lái)定義。Common Lisp也沒(méi)有C語(yǔ)言的優(yōu)勢(shì):在每一個(gè)平臺(tái)上都是一種支配性的執(zhí)行或流行的執(zhí)行。每個(gè)版本都應(yīng)執(zhí)行上述標(biāo)準(zhǔn),但有一些細(xì)節(jié)要由編譯器或注釋器來(lái)處理,這使 得每個(gè)執(zhí)行都稍有不同。 你可以使用幾種選項(xiàng)——在本文中我使用CLISP,它在Windows、Linux和Mac(僅PPC)上運(yùn)行良好。如果你使用英特爾Mac,則必須使用其它執(zhí)行,如Allegro Common Lisp或SBCL。對(duì)于這篇快速入門中的簡(jiǎn)單例子,你使用哪個(gè)執(zhí)行都不要緊。 使用Lispbox可 以快速安裝Common Lisp系統(tǒng),Lispbox為你提供一個(gè)Common Lisp執(zhí)行、Emacs和SLIME——Emacs高級(jí)Lisp整合模式,許多Lisp程序員會(huì)告訴你說(shuō),它是使用Lisp的唯一方法。如果你并非 Emacs用戶(我本人也和你一樣),不要擔(dān)心,它并非必要條件,只是使得編寫Common Lisp程序更加簡(jiǎn)便。 安裝過(guò)程因平臺(tái)而異,在Windows中你只能運(yùn)行安裝程序,多數(shù)Linux軟件包管理器提供安裝包等。選擇一個(gè)執(zhí)行并遵循安裝指令即可。打開REPL(交互式提示符)之后再返回這里,我們繼續(xù)往后講。 REPL REPL代表“閱讀-評(píng)估-打印-循環(huán)”(Read-Evaluate-Print-Loop),它簡(jiǎn)單表示注釋器的一個(gè)交互式提示符。你可以從這 里輸出一些簡(jiǎn)單的Lisp代碼。如果你使用另一種注釋器提示符,你可以在這里使用提示符作為計(jì)算器輸出一些基本的數(shù)學(xué)表達(dá)式——但它不能正常運(yùn)行。在 CLISP中輸入5*2不會(huì)返回任何有意義的結(jié)果: [1]> 5 * 2 5 [2]> 5 [3]> 2 Lisp并非以那種方式運(yùn)行,運(yùn)算符,如“+”不是在數(shù)字之間,而是在數(shù)字前面,就好像它們是函數(shù)名稱一樣。因此,如果你想將REPL當(dāng)作計(jì)算器使用,你必須輸入: [1]> (* 5 2) 10 [2]> (+ 1 2 3 4) 10 [3]> (+ (* 5 2) (* 10 3) (/ 100 4)) 65 對(duì)你來(lái)說(shuō),理解這種用法可能更難一些,但它擁有一些優(yōu)勢(shì):它便于編譯器解析、它對(duì)所有函數(shù)和運(yùn)算符都一樣、它讓你給函數(shù)添加盡可能多的自變量——例如,在上面的第二個(gè)例子中,你可以任意擴(kuò)充加數(shù),使得加法函數(shù)和總計(jì)函數(shù)完全一樣。 另外你會(huì)注意到,函數(shù)名在括號(hào)內(nèi),而不像許多其它語(yǔ)言一樣函數(shù)名在括號(hào)以外。這表示你要寫(函數(shù)自變量)而不是函數(shù)(自變量)。 每個(gè)Lisp表達(dá)式會(huì)返回一個(gè)值,一個(gè)函數(shù)總是返回最后一個(gè)表達(dá)式的結(jié)果——即使是NIL,NULL在Java或C++中的對(duì)等值也是這樣。因此在Lisp中顯示“Hello World”相當(dāng)簡(jiǎn)單: [3]> "Hello World" "Hello World" 如果你希望在屏幕上打印一些內(nèi)容,并返回其它內(nèi)容,你應(yīng)該使用打印函數(shù): [4]> (print "Hello World") "Hello World" "Hello World" 這個(gè)字符串顯示兩次,一個(gè)是打印結(jié)果,一個(gè)是函數(shù)返回的結(jié)果。 Lisp表示LIST Processor(列表處理器),Lisp中的幾乎所有內(nèi)容都以列表的形式存在,因此有時(shí)你必須處理列表。定義列表非常容易: [5]> (list 1 2 3 4 5) (1 2 3 4 5) [6]> ‘(1 2 3 4 5) (1 2 3 4 5) 第二種定義方法叫做引用,除定義簡(jiǎn)單的列表外,它還有更多用途,不過(guò)我們必須在后面的另一篇文章中討論那個(gè)主題。 控制流程 Lisp擁有全部標(biāo)準(zhǔn)控制流程方法。定義一個(gè)重復(fù)一個(gè)值的簡(jiǎn)單循環(huán)相當(dāng)容易: [7]> (dotimes (i 10) (print i))0 1 2 3 4 5 6 7 8 9 NIL 同樣,重復(fù)一個(gè)列表也很簡(jiǎn)單: [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 以上兩個(gè)函數(shù)都是DO函數(shù)的特殊版本,它就像在其它語(yǔ)言中組合使用while和for函數(shù)一樣。它由三個(gè)部分組成:循環(huán)變更定義、終止條件和語(yǔ)句主體: [9]> (do ((i 0 (+ 1 i))) ((> i 10)) (print i)) 0 1 2 3 4 5 6 7 8 9 10 NIL 在這個(gè)例子中,變更定義部分為((i 0 (+ 1 i))),它定義變量i為0,并在每次循環(huán)時(shí)調(diào)用函數(shù)(+ 1 0)。終止條件為((> i 10)),表示在i大于10時(shí)函數(shù)終止運(yùn)行。最后主體部分打印i的值。 Lisp中也有條件函數(shù),最基本的條件函數(shù)為if函數(shù): [10]> (if (> 10 20) (print "Hello") (print "World")) "World" "World" if函數(shù)由三部分組成:條件、then語(yǔ)句和else語(yǔ)句。如果條件為真,則執(zhí)行then語(yǔ)句,否則就執(zhí)行else語(yǔ)句。 你可能已經(jīng)注意到,到現(xiàn)在為止我們僅使用了單個(gè)的語(yǔ)句——但如果你需要把幾個(gè)語(yǔ)句連接在一起,那該怎么辦呢?在Lisp中,要將幾個(gè)語(yǔ)句連接起來(lái),你需要使用progn這個(gè)特殊的控制流程函數(shù): [11]> (progn (print "Hello") (print "World")) "Hello" "World" "World" 例如,上例允許你在條件函數(shù)和循環(huán)中使用幾個(gè)語(yǔ)句。 好了,以上內(nèi)容已足以讓你初步認(rèn)識(shí)Common Lisp語(yǔ)言:通過(guò)你了解的內(nèi)容,你可以編寫出一些微型程序,對(duì)Lisp語(yǔ)言進(jìn)行測(cè)試。請(qǐng)密切關(guān)注本系列的下一篇文章,到時(shí)我們將介紹Lisp獨(dú)特的列表處理機(jī)制。 責(zé)任編輯:德東 |
|
|
來(lái)自: ShangShujie > 《pptr……》