Lisp介紹之七個(gè)原始操作符
本文是paul graham所著的《Lisp之根源》的第一部分,在對Lisp的介紹中,描述了Lisp中的七個(gè)原始操作符。這是一篇非常不錯(cuò)的Lisp介紹文,值得一讀。
約翰麥卡錫于1960年發(fā)表了一篇非凡的論文,他在這篇論文中對編程的貢獻(xiàn)有如歐幾里德對幾何的貢獻(xiàn).1 他向我們展示了,在只給定幾個(gè)簡單的操作符和一個(gè)表示函數(shù)的記號的基礎(chǔ)上, 如何構(gòu)造出一個(gè)完整的編程語言. 麥卡錫稱這種語言為Lisp, 意為List Processing, 因?yàn)樗闹饕枷胫皇怯靡环N簡單的數(shù)據(jù)結(jié)構(gòu)表(list)來代表代碼和數(shù)據(jù).
值得注意的是,麥卡錫所作的發(fā)現(xiàn),不僅是計(jì)算機(jī)史上劃時(shí)代的大事, 而且是一種在我們這個(gè)時(shí)代編程越來越趨向的模式.我認(rèn)為目前為止只有兩種真正干凈利落, 始終如一的編程模式:C語言模式和Lisp語言模式.此二者就象兩座高地, 在它們中間是尤如沼澤的低地.隨著計(jì)算機(jī)變得越來越強(qiáng)大,新開發(fā)的語言一直在堅(jiān)定地趨向于Lisp模式. 二十年來,開發(fā)新編程語言的一個(gè)流行的秘決是,取C語言的計(jì)算模式,逐漸地往上加Lisp模式的特性,例如運(yùn)行時(shí)類型和無用單元收集.
在這篇文章中我盡可能用最簡單的術(shù)語來解釋約翰麥卡錫所做的發(fā)現(xiàn). 關(guān)鍵是我們不僅要學(xué)習(xí)某個(gè)人四十年前得出的有趣理論結(jié)果, 而且展示編程語言的發(fā)展方向. Lisp的不同尋常之處--也就是它優(yōu)質(zhì)的定義--是它能夠自己來編寫自己. 為了理解約翰麥卡錫所表述的這個(gè)特點(diǎn),我們將追溯他的步伐,并將他的數(shù)學(xué)標(biāo)記轉(zhuǎn)換成能夠運(yùn)行的Common Lisp代碼.
七個(gè)原始操作符
開始我們先定義表達(dá)式 .表達(dá)式或是一個(gè)原子 (atom),它是一個(gè)字母序列(如 foo),或是一個(gè)由零個(gè)或多個(gè)表達(dá)式組成的表 (list), 表達(dá)式之間用空格分開, 放入一對括號中. 以下是一些表達(dá)式:
- foo
- ()
- (foo)
- (foo bar)
- (a b (c) d)
最后一個(gè)表達(dá)式是由四個(gè)元素組成的表, 第三個(gè)元素本身是由一個(gè)元素組成的表.
在算術(shù)中表達(dá)式 1 + 1 得出值2. 正確的Lisp表達(dá)式也有值. 如果表達(dá)式e 得出值v ,我們說e 返回 v . 下一步我們將定義幾種表達(dá)式以及它們的返回值.
如果一個(gè)表達(dá)式是表,我們稱第一個(gè)元素為操作符 ,其余的元素為自變量 .我們將定義七個(gè)原始(從公理的意義上說)操作符: quote,atom,eq,car,cdr,cons,和 cond.
(quote x ) 返回x .為了可讀性我們把(quote x )簡記 為'x . Lisp代碼
- > (quote a)
- a
- > 'a
- a
- > (quote (a b c))
- (a b c)
(atom x )返回原子t如果x 的值是一個(gè)原子或是空表,否則返回(). 在Lisp中我們按慣例用原子t表示真, 而用空表表示假. Lisp代碼
- > (atom 'a)
- t
- > (atom '(a b c))
- ()
- > (atom '())
- t
既然有了一個(gè)自變量需要求值的操作符, 我們可以看一下quote的作用. 通過引用(quote)一個(gè)表,我們避免它被求值. 一個(gè)未被引用的表作為自變量傳給象 atom這樣的操作符將被視為代碼:
- > (atom (atom 'a))
- t
反之一個(gè)被引用的表僅被視為表, 在此例中就是有兩個(gè)元素的表:
- > (atom '(atom 'a))
- ()
這與我們在英語中使用引號的方式一致. Cambridge(劍橋)是一個(gè)位于麻薩諸塞州有90000人口的城鎮(zhèn). 而``Cambridge''是一個(gè)由9個(gè)字母組成的單詞.
引用看上去可能有點(diǎn)奇怪因?yàn)闃O少有其它語言有類似的概念. 它和Lisp最與眾不同的特征緊密聯(lián)系:代碼和數(shù)據(jù)由相同的數(shù)據(jù)結(jié)構(gòu)構(gòu)成, 而我們用quote操作符來區(qū)分它們.
(eq x y )返回t如果x 和y 的值是同一個(gè)原子或都是空表, 否則返回(). Lisp代碼
- > (eq 'a 'a)
- t
- > (eq 'a 'b)
- ()
- > (eq '() '())
- t
(car x )期望x 的值是一個(gè)表并且返回x 的第一個(gè)元素. Lisp代碼
- > (car '(a b c))
- a
(cdr x )期望x 的值是一個(gè)表并且返回x 的第一個(gè)元素之后的所有元素.
- > (cdr '(a b c))
- (b c)
(cons x y )期望y 的值是一個(gè)表并且返回一個(gè)新表,它的第一個(gè)元素是x 的值, 后面跟著y 的值的各個(gè)元素. Lisp代碼
- > (cons 'a '(b c))
- (a b c)
- > (cons 'a (cons 'b (cons 'c '())))
- (a b c)
- > (car (cons 'a '(b c)))
- a
- > (cdr (cons 'a '(b c)))
- (b c)
(cond ( ... ) ...( ... )) 的求值規(guī)則如下. p 表達(dá)式依次求值直到有一個(gè)返回t. 如果能找到這樣的p 表達(dá)式,相應(yīng)的e 表達(dá)式的值作為整個(gè)cond表達(dá)式的返回值.
- > (cond ((eq 'a 'b) 'first)
- ((atom 'a) 'second))
- second
當(dāng)表達(dá)式以七個(gè)原始操作符中的五個(gè)開頭時(shí),它的自變量總是要求值的.2 我們稱這樣 的操作符為函數(shù) .
以上就是Lisp介紹中有關(guān)其他原始操作符的描述。
【編輯推薦】