LISP

Lisp，是具有悠久歷史的計算機程式語言家族，有獨特的完全用圓括號的字首符號表示法。它起源於1958年，是現今第二悠久而仍廣泛使用的高階程式語言，只有FORTRAN程式語言比它更早一年。Lisp程式設計語族已經演變出許多種方言，現代最著名的通用程式設計方言是Scheme、Common Lisp和新近的Clojure。簡介.Lisp最初是為計算機程式建立的實用數學表示法，當時借鑒過阿隆佐·邱奇的lambda表示法。它很快成為人工智慧研究中最受歡迎的程式語言。作為早期的高階程式語言之一，Lisp開創了電腦科學領域的許多概念，包括樹結構、自動記憶體管理、動態型別、條件表示式、高階函式、遞迴、、讀取﹣求值﹣輸出迴圈。"LISP"名稱源自「列表處理器」的縮寫。列表是Lisp的主要資料結構之一，Lisp程式設計程式碼也同樣由列表組成。因此，Lisp程式可以把原始碼當作資料結構進行操作，而使用其中的宏系統，開發人員可將自己定義的新語法或領域專用的語言，嵌入在Lisp程式設計中。程式碼和資料的可互換性為Lisp提供了立即可辨識的語法。所有的Lisp程式程式碼都寫為S-表示式或以括號表示的列表。函式呼叫或語義形式也同樣寫成列表，首先是函式或運算子的名稱，然後接著是一或多個引數：例如，取三個引數的函式codice_1即為。歷史.Steve Russell在1958年，約翰·麥卡錫在麻省理工學院發明瞭Lisp程式語言。在1960年，他在《ACM通訊》發表了論文《符號表示式的遞迴函式及其機器計算，第一部份》。在這篇論文中闡述了只要透過一些簡單的運運算元，以及借鑒自阿隆佐·邱奇的用於匿名函式的表示法，就可以建立一個可用於演演算法中的具圖靈完備性的語言。Lisp還採納了在1955年至1956年間建立的資訊處理語言所提出的列表處理與遞迴概念。約翰·麥卡錫在最初定義的Lisp之中，先將程式表達為，舉例來說的codice_2，等同於S-表示式的。S-表示式可以將複雜結構表示為列表，在Lisp被實現了之後，程式設計者一般只使用S-表示式，而棄用M-表示式，這使得程式具備了同像性，即程式與資料由同樣的結構儲存。M-表示式曾短暫存續於Horace Enea的和的之中。第一個Lisp實作是在IBM 704機器上使用打孔卡寫出的。史帝芬·羅素在閱讀完約翰·麥卡錫的論文後，認為其中的codice_3函式可以用機器碼來實作，從而創造了一個能工作的Lisp直譯器。直譯器可以用來執行Lisp程式，或者更恰當的說為：“求值Lisp表示式”。在1960年發表的LISP I中，研究生Daniel Edwards開發了垃圾回收程式，使得在通用計算機上執行Lisp變得可行。在1962年，Timothy Hart與Michael Levin在麻省理工學院以Lisp自身，實做出第一個完整的Lisp編譯器。在1963年，Timothy Hart提議向LISP 1.5增加宏。在1975年，傑拉德·薩斯曼和蓋伊·史提爾二世開發了Scheme，它是使用詞法作用域和尾呼叫最佳化的第一個Lisp方言。在1980年代至1990年代期間，蓋伊·史提爾二世、、、和等人，在將當時新近的Lisp方言，其多數是Maclisp的後繼者比如ZetaLisp和NIL，統一成單一語言上進行了巨大的努力。新語言Common Lisp，在某種程度上兼容於它所替代的方言。在1994年，ANSI出版了Common Lisp標準《ANSI X3.226-1994資訊科技程式語言Common Lisp》。此外還有嵌入到編輯器Emacs中的Emacs Lisp，它非常流行並建立了自己的標準。聯絡於人工智慧.自從創始以來，Lisp就密切聯絡於人工智慧研究社群，特別是在PDP-10系統之上。在1970年傑拉德·薩斯曼和特里·威諾格拉德使用Lisp實現了程式語言，它被用在著名的AI系統SHRDLU之中。譜系和方言.在它六十餘年的歷史中，Lisp產生了在S-表示式語言的核心主旨上的很多變體。此外，每個給定方言又可能有多種實現，例如Common Lisp就有十餘種以上的實現。在一種標準化了的方言之內，符合標準的實現支援相同的核心語言，但是有著不同的擴充套件和函式庫。在方言間的差異可能是非常顯眼的，例如定義一個函式，Common Lisp使用Maclisp在1969年介入的關鍵字codice_4，而Scheme使用它在1975年介入的codice_5。和在1998年的一篇論文中，按採用統一的還是分立的函式與值名稱空間，將Lisp家族語言劃分為Lisp1和Lisp2。2000年迄今.在1990年代衰退之後，Lisp在2000年之後因一些關注而逐漸復甦。當其他人認為Lisp已經過時陳舊，受到保羅·格雷厄姆和埃裡克·雷蒙等人關於Lisp的著作的啟發，很多新的Lisp程式設計者經常將其描述為令人大開眼界的經驗，並聲稱在本質上比較其它程式語言更有生產效率。這種意識的提高可對比於“人工智慧冬季”和Lisp在1990年代中期的短暫增長。Common Lisp開源社群建立了至今仍活躍的支援基礎有：，它是收集Common Lisp相關資訊的維基；Planet Lisp，它是收集了各種Lisp相關部落格的內容；Common-lisp.net，它是開源專案的託管站點；Quicklisp，它是含括了許多函式庫的裝載管理器。在Common-lisp.net上，推薦了6種開源和2種商業Common Lisp實現。Scheme社群基於廣泛接納的R5RS語言標準，開發了一些活躍至今的實作如Chicken、Gambit、、Larceny和等。建立了很多準標準函式庫和Scheme擴充套件功能。隨著Scheme實作使用者社群增長，始自2003年的語言標準化過程在2007年產生了R6RS標準，在2013年又通過了R7RS-small最終草案，它已經有了一些實現支援。使用Scheme介紹電腦科學課程的學校似乎有所減少，麻省理工學院的電腦科學入門課程，已經不再使用Scheme。Clojure是在2007年出現的新近Lisp方言，它編譯至Java虛擬機器並特別關注併發性。現今與Lisp有關的大多數新活動，包括開發新的跨平臺函式庫和應用，都集中在Scheme、Common Lisp、Emacs Lisp、Racket和Clojure的實作上。近年來又有了幾種新的Lisp方言：Arc、Hy、、Axel和Fennel。此外，在2007年出現的，是OS X上採用Lisp式語法的指令碼語言；在2012年出現的Julia所採用的語法解析器，是用Scheme方言Femtolisp實現的。在2019年10月，保羅·格雷厄姆釋出了一個新的Lisp方言Bel。主要方言.Common Lisp和Scheme是Lisp發展的兩大主流的代表。這些語言體現了顯著不同的設計選擇。Common Lisp是Maclisp的後繼者。對它有重要影響的是、Maclisp、、、和Scheme。它擁有用於程式設計Lisp機器的大型Lisp方言Lisp Machine Lisp的很多特徵，但設計上能高效的實現在任何個人計算機或工作站上。Common Lisp是通用程式語言，因而擁有一個大型語言標準，包括很多內建資料型別、函式、宏和其他語言元素，以及一個物件系統，即Common Lisp物件系統。Common Lisp還從Scheme借鑑了特定特徵，比如詞法作用域和詞法閉包。Common Lisp實現目標定為不同的平臺，比如：LLVM、Java虛擬機器、x86-64、PowerPC、Alpha、ARM、Motorola 68000和MIPS，和不同的作業系統，比如：Windows、macOS、Linux、Solaris、FreeBSD、NetBSD、OpenBSD、Dragonfly BSD和Heroku。Scheme是一個靜態作用域和適當尾遞迴的Lisp程式語言方言。它的設計有著異常清晰和簡單的語義，和很少的形成表示式的不同方式。它的設計大約比Common Lisp早上一個年代，Scheme是一個相當極簡主義的設計。它擁有非常小的標準特徵集合，但具有在Common Lisp中未規定的特定實現特徵，比如尾遞迴最佳化和完全續體。在Scheme中能方便的表達廣闊的程式設計範型，包括指令式、函式式和訊息傳遞風格。Scheme透過一系列的標準，即第n次修訂的演算法語言Scheme報告，和一系列而持續的演化。Clojure是Lisp的一個新近方言，其目標主要是Java虛擬機器、通用語言執行庫和編譯成JavaScript，它被設計為一個務實的通用程式語言。Clojure受到了Haskell的相當大的影響，因而非常強烈的強調了不可變性。Clojure提供了對Java框架和庫的訪問，具有可選的型別提示和型別推論，這樣到Java的呼叫就可以避免反射並確使了快速的原始操作。Clojure設計上不後向兼容於其他Lisp方言。進一步的，Lisp方言在很多應用中被用作指令碼語言，其中最周知的是在Emacs編輯器中的Emacs Lisp，在AutoCAD中的AutoLISP和後來的Visual Lisp，Audacity中的，和LilyPond中GNU Guile。有用的Scheme直譯器潛在有很小的大小，使得它特別流行於嵌入式指令碼。例子包括SIOD和TinyScheme，二者都曾經以共用名字“Script-fu”成功的嵌入到了GIMP影象處理軟體中。LIBREP是John Harper最初基於Emacs Lisp語言開發的Lisp直譯器，它已經嵌入到了Sawfish視窗管理器。標準化的方言.Lisp有官方標準化和業界標準的方言：IEEE Scheme、ANSI Common Lisp、ISO ISLISP、R5RS Scheme和R7RS-small Scheme。注意：本文的例子是用Common Lisp書寫，但是其中的多數在Scheme中也是有效的，示例採用的Common Lisp實現是SBCL。語法和語義.符號表達式.Lisp是一個。不同於多數其他語言，在表示式和語句之間不做區分。所有程式碼和資料都寫為表示式。當求值一個表示式的時候，它產生一個值，它可以接著被嵌入到其他表示式中。每個值都可以是任何資料型別的。McCarthy的1958年論文介入兩種型別的語法：表示式即S-表示式或sexps，它映象了程式碼和資料的內部表示；和元表示式即，它是與S-表示式對應的用類似數學符號表達的函式。M-表示式從未得到青睞，幾乎所有今天的Lisp都使用S-表示式來操縱程式碼和資料二者。大量而單一的使用圓括號，是Lisp與其他程式語言家族最直接明顯的差別。為此學生們一直將Lisp戲稱為：“迷失在愚蠢的括號中”。有賴於表示式給予了語言巨大的靈活性。由於Lisp函式都寫為列表，它們可以完全就像資料那樣處理。這允許了輕易的書寫能操縱其他程式的程式，即進行超程式設計。很多Lisp方言使用宏系統來利用這個特徵，它確使了語言擴充套件而幾乎沒有限制。列表.書寫Lisp列表，是以空白來分隔其元素，幷包圍以圓括號。例如，是其元素為三個原子、和的一個列表。這些值是隱含的有型別的：它們分別是兩個整數和叫做“符號”的Lisp專有資料型別，但不需要顯式的宣告。空列表也表示為特殊原子。這是Lisp中既是原子又是列表的唯一實體。表示式被寫為使用字首表示法的列表。在列表中第一個元素是一個函式的名字、一個宏的名字、一個lambda表示式或特殊算符的名字。列表的餘下部份是實際引數。例如，函式將它的實際引數作為一個列表返回，所以表示式：在前面例子中的之前的codice_6是特殊算符，它不求值就返回它的實際引數。任何未引述的表示式，在外圍表示式被求值之前，都遞迴的被求值。例如：注意第三個實際引數是一個列表；列表是可以巢狀的。算符.對算術算符的對待都是類似的。表示式：10其在中綴表示法下的等價形式為：。Lisp沒有在Algol派生語言中實現的那樣的算符概念。在Lisp中算術算符是可變引數函式，能夠接受任何數目的實際引數。C-風格的codice_7增加算符，有時在名字codice_8之下實現，給出的語法是：01等價於codice_9，它返回codice_10的新值。特殊算符提供了Lisp的控制結構。例如，特殊算符接受三個實際引數。如果第一個實際引數為非codice_11，它求值為第二實際引數；否則它求值為第三個實際引數。因此表示式：(list 1 2 "foo")(list 3 4 "bar"))當然，如果在的位置替換上非平凡的表示式會更有用處。Lisp還提供邏輯算符codice_12、codice_13和codice_14。codice_12和codice_13算符進行短路求值，並分別返回它們的第一個codice_11或非codice_11實際引數："James"Lambda表示式和函式定義.另一個特殊算符，被用來繫結變數到值，接著對錶達式求進行求值。這個算符還被用於建立函式：給的實際引數是一個形式引數列表，和這個函式要求值的一個或多個表示式，它的返回值是其求值的最後一個表示式的值。表示式：求值為一個函式，它接受一個實際引數，繫結它到並返回比這個實際引數大codice_19的數。對待Lambda表示式於命名函式沒有區別；它們以相同方式呼叫。如下表達式：6這裡我們做了一次函式應用：我們透過傳遞給它值codice_20而執行了這個匿名函式。命名函式是透過使用codice_4宏，將一個lambda表示式儲存在一個符號之中而建立的：FOO在全域性環境中定義一個名為的新函式。它在概念上類似於表示式：這裡的是一個宏，用來設定第一個實際引數為一個新的函式物件。是對命名為的函式的全域性函式定義。是特殊算符的簡寫，它返回指定函式在當前詞法環境下的一個函式物件。作用域和閉包.按照變數的作用域，可將Lisp家族劃分為兩大支系，分別使用動態作用域，或使用靜態作用域。Scheme、Common Lisp和Clojure預設使用靜態作用域，而AutoLISP、PicoLisp和newLISP使用動態作用域。Emacs Lisp自從Emacs版本24.1起使用動態和詞法作用域二者。原子.在最初的LISP中，有兩種基礎資料型別：原子和列表。列表是元素的一個有限有序序列，這裡的每個元素要麼是一個原子要麼是一個列表，而原子要麼是一個數要麼是一個符號。符號實質上是唯一性命名的專案，在原始碼中寫為字母數字串，並被要麼用作一個變數名字要麼中的一個數據專案。例如，列表包含三個元素：符號、列表和數codice_22。在原子和列表之間的本質區別是原子是不可變的和唯一性的。出現在原始碼中不同位置的兩個原子，如果以完全相同方式寫成則表示相同的物件，而每個列表都是一個分立的物件，它們可以獨立於其他列表而改變 ，並可以透過比較算符而區分於其他列表。隨著後來的Lisp介入了更多的資料型別，和程式設計風格的演化，原子的概念失去了重要性。很多方言出於遺產相容性而保留了謂詞codice_23，定義它為對不是codice_24的任何物件都為真。cons和列表.Lisp列表被實現為單向連結串列。這個連結串列的每個單元都叫做codice_24，它構成自兩個指標，分別叫做codice_27和codice_27。在眾多可以用codice_24單元構建的資料結構中，最基本一個叫做“適當列表”，而指向另一個適當列表。如果一個給定codice_24被接受為一個連結串列的頭部，那麼它的codice_33指向這個列表的第一個元素，而它的codice_34指向這個列表的餘下部份。為此，在提及作為連結串列一部份的codice_24的時候，和函式也分別叫做和。因此，Lisp列表不是原子物件，它們類似C++或Java中的容器類的例項。一個列表就是連結的codice_24的一個聚集。引用一個給定列表的變數，簡單的就是到列表中第一個codice_24的指標。遍歷一個列表可以透過逐一codice_34這個列表來進行，就是說連續的選取codice_34來訪問這個列表的每個codice_24；或者透過使用任何一個將一個函式對映在一個列表之上的高階函式。由於codice_24和列表在Lisp系統中是普遍性的，經常有人誤解它們是Lisp的唯一資料結構。事實上，除了最簡單者之外的所有Lisp都有其他資料結構，比如向量、散列表、結構等等。S-表示式表示列表.圓括號的S-表示式表示了連結串列結構。有多種方式將相同的列表表示為一個S-表示式。codice_24可以用“點對錶示法”寫為，這裡的是codice_33而是codice_34。更長的適當列表可以用點對錶示法寫為。這通常簡寫為列表表示法的。“不適當列表”，可以用這二種表示法的組合來書寫，比如列表有三個codice_24，最後的codice_34是，它就是完全特殊形式下的。列表處理過程.Lisp提供很多內建的過程，用來訪問和控制列表。列表可以直接用過程建立，它接受任何數目的實際引數，並返回這些實際引數的列表：由於列表是從cons對構造而來，可以使用過程來在一個列表的前端增加一個元素。注意由於列表構造方法，在處理列表實際引數上是不對稱的：過程將兩個列表相互附加。由於Lisp列表是連結串列，附加兩個列表有漸進時間複雜度 formula_1：共享結構.Lisp列表，作為單向連結串列，可以相互共享結構。就是說，兩個列表可以有相同的尾部，或者最終的codice_24序列。例如，在執行下列Common Lisp程式碼之後：尾部在兩個列表中都是相同的結構。它不是復件；對於兩個列表指向和的codice_24單元都在相同的記憶體位置。共享結構而非複製可以得到相當客觀的效能提升。但是這種技術可能以未預期的方式，交互於改變作為實際引數傳遞給它的列表的那些函式。改變一個列表，比如替代為，將會影響另一個列表：GOOSE不僅變更codice_49，還變更了codice_50，這可能是未預期的結果。這是缺陷的為此改變它們的實際引數的那些函式被文件標示為破壞性的。函數語言程式設計愛好者避免破壞性函式。在青睞函式式風格的Scheme方言中，破壞性函式的名字都標記了警告性感嘆號，或者叫做“bang”，比如，接著將破壞性呼叫作為最佳化增加於可以安全的進行它們的地方。自求值形式和引述.Lisp求值使用者錄入的表示式。符號和列表求值為某個其他表示式，例如：一個符號求值為它指名的變數的值；求值為。但是，多數其他形式求值為其自身：如果錄入到Lisp中，它返回。任何表示式都可以加上防止被求值的標記，這對於符號和列表是需要的。特殊算符承擔了這個角色，它也簡寫為。要引用這個符號，錄入要麼 ，要麼更常見的。Common Lisp和Scheme二者還支援“反引述”。如果變數有值，則求值為，而求值為。反引述經常用於定義宏展開。自求值形式和引述形式是Lisp中的等價者。在程式程式碼中可以修改文字的值。例如，如果一個函式返回一個引述形式，而呼叫這個函式的程式碼修改這個形式，這可以改變這個函式在後續呼叫時的行為：'(one two three))SHOULD-BE-CONSTANT(setf (third stuff) 'bizarre))BIZARRE像這樣修改一個引述形式通常被認為是不良風格，並且被ANSI Common Lisp定義為是危險的。它會導致在編譯檔案中的未定義的行為，因為檔案編譯器可以合併類似的常量並將它們放置到防寫記憶體中，等等。Lisp的引述形式化已經被Douglas Hofstadter和其他人註解為自引用的哲學想法的例子。控制結構.Lisp最初有很少的控制結構，但是在語言演化期間卻增加了很多。Lisp最初的條件算符是，它或被視為後來的結構的先驅。Scheme方言的程式設計者經常使用尾遞迴表達迴圈。Scheme在學術計算機科學中的通行性，導致了一些學生相信尾遞迴是在Lisp中書寫迭代的唯一的或最常用的方式，但是這是不正確的。所有常見的Lisp方言都有指令式風格的迭代構造，從Scheme的迴圈到Common Lisp的複雜的表示式。此外，使之成為客觀而非主觀事物的關鍵要點，是Scheme對尾遞迴的處理提出了特殊要求，Scheme通常鼓勵使用尾遞迴的原因，是語言定義明確的支援了這種實踐。與之相反，ANSI Common Lisp不要求常稱為尾遞迴消除的這種最佳化。因此，不鼓勵將尾遞迴風格作為使用更傳統的迭代構造的替代品。在Common Lisp中不只是風格偏好的問題，而是潛在的效率問題，這是因為在Common Lisp中明顯的尾遞迴可能未被編譯為簡單的codice_53；並且也是程式正確性問題，這是因為在Common Lisp中尾遞迴可能增加棧的使用而有堆疊溢位風險。一些Lisp控制構造是特殊算符，等價於其他語言的語法關鍵字。使用這些算符的表示式與函式呼叫有著相同的表面外觀，但是不同之處在於引數不是必須求值的，或者在迭代表達式的情況下，可以被求值多於一次。對比於多數其他主要程式語言，Lisp允許使用語言自身實現控制結構。一些控制結構被實現為Lisp宏，想知道它們是如何工作的程式設計者甚至可以透過宏展開來研究。Common Lisp和Scheme二者都有非區域性控制流程算符。在這些算符中的不同是在這兩種方言之間最深的差異。Scheme使用過程支援可重入的續體，它允許一個程式儲存執行中的特定位置。Common Lisp不支援可重入的續體，但是支援處理逃脫續體的一些方式。相同的演算法在Lisp中經常可以用要麼指令式要麼函式式風格來表達。如上所述，Scheme趨於青睞函式式風格，使用尾遞迴和續體來表達控制流程。但是，指令式風格仍是很有可能的。很多Common Lisp程式設計者偏好的風格，可能讓使用結構化程式語言比如C的程式設計者看著更加熟悉，而Scheme程式設計者偏好的風格更加密切類似於純函數語言程式設計語言比如Haskell。由於Lisp在列表處理上的早期遺產，它擁有與在序列上迭代有關的一組廣泛的高階函式。在其他語言中需要顯式迴圈的很多情況下，在Lisp和很多函數語言程式設計語言中，相同的任務可以透過高階函式來完成。一個好的例子是在Scheme中叫做而在Common Lisp中叫做的函式。給定一個函式和一個或多個列表，按順序將這個函式依次應用到這些列表的元素之上，並將結果收集入一個新的列表：這個codice_54函式將函式應用於每個對應的元素對之上。程式程式碼的列表結構.在Lisp和其他語言之間的基本區別是，在Lisp中一個程式的文字表示，簡單的是人類可讀的描述，它同於底層Lisp系統使用的內部資料結構（連結串列、符號、數、字元等)。Lisp利用這一點來實現了一個非常強力的宏系統。就像其他宏語言比如C，一個宏返回可以接著被編譯的程式碼。但是不同於C的宏，Lisp的宏是函式因而可以利用Lisp的全部能力。進一步的，因為Lisp程式碼作為列表有著相同的結構，宏可以使用語言中任何列表處理函式來建造。簡要的說，Lisp可以在資料結構上做的任何事情，Lisp宏都可以在程式碼上做。相反的，在多數其他語言中，解析器的輸出是純粹的內部於語言實現的而不能被程式設計者操縱。這個特徵可以在語言中開發高效語言。例如，Common Lisp物件系統可以使用宏清晰的實現為一個語言擴充套件。這意味著如果一個應用需要不同的繼承機制，它可以使用不同的物件系統。這直接的對立於多數其他語言；例如，Java不能支援多重繼承並且沒有增加它的合理方式。在簡單的Lisp實現中，這個列表結構被直接的解釋來執行這個程式；一個函式是在文字上的一段列表結構，它被直譯器在執行它的時候遍歷。但是，多數後來的Lisp系統還包括一個編譯器。編譯器將列表結構轉換成機器程式碼或位元組碼用於執行。這個程式碼可以像用常規語言比如C編譯的程式碼一樣快速。宏在編譯步驟之前展開，因而提供一些有價值的選項。如果一個程式需要一個預先計算了的表格，那麼一個宏可以在編譯時間建立這個表格，所以編譯器只需要輸出這個表格，而不需要在執行時間呼叫程式碼來建立這個表格。一些Lisp實現甚至擁有一種codice_55機制，允許程式碼在編譯時間期間出現，而不出現在發行的模組中。求值和讀取–求值–列印迴圈.Lisp語言經常被以互動式命令列來使用，它還可以結合入整合開發環境。REPL的基本操作描述如下。這是一個簡化的描述，省略了很多真實Lisp的元素，比如引述和宏。函式接受文字的S-表示式作為輸入，並將它們解析為內部資料結構。例如，如果你在提示符下錄入文字，將它轉換成有三個元素的一個連結串列：符號、數codice_19和數codice_22。恰巧這個列表也是一段有效的Lisp程式碼，就是說它是可以被求值的。這是因為codice_33這個列表指名了一個函式即加法運算。注意將被讀作一個單一符號。將被讀作數一百二十三。將被讀作字串codice_59。函式求值資料，返回零或多個其他Lisp資料作為結果。求值不必然意味著解釋；一些Lisp系統編譯所有的表示式為機器程式碼。但將求值描述為解釋是很簡單的：要求值其codice_33指名一個函式的一個列表，首先求值在它的codice_34中的每個實際引數，接著應用這個函式於這些實際引數。在這個案例中，這個函式是加法，而應用它於實際引數列表產生答案。這是這個求值的結果。符號求值為符號codice_49的值。資料比如字串codice_59求值為相同的字串。列表求值為列表codice_64。函式的工作是將輸入表示給使用者。對於簡單結果比如這是平凡的。求值為一段列表結構的一個表示式會要求遍歷這個列表並將結果輸出為一個S-表示式。要實現一個Lisp REPL，必需的只是實現這三個函式和一個無限迴圈函式。實現函式會很複雜是自然的，因為它必須也要實現所有特殊算符比如或。它們完成後，一個基本的REPL就是一行程式碼：。Lisp REPL典型的也提供輸入編輯、輸入歷史、錯誤處理和到偵錯程式的介面。Lisp通常使用及早求值。在Common Lisp中，實際引數以應用式次序求值，而在Scheme中實際引數的次序是未定義的，為編譯器最佳化留下了餘地。語言創意.保羅·格雷厄姆辨識出Lisp區別於其他現存的語言如Fortran的九個重要特徵：Lisp是將程式程式碼的結構忠實而直接的表示為標準資料結構的第一個語言，這種品質後來被稱為“同像性”。故而Lisp函式可以在Lisp程式中被操縱、更改、甚至建立，而不用低層操縱。 這通常被認為是語言表達能力方面的主要優勢之一，使得語言適合於語法宏和元迴圈求值。條件表示式是麥卡錫用Fortran寫一個象棋程式時發明的，他提議將其包含在ALGOL中但未被採納。Lisp中的條件表示式使用了一般性的codice_65結構，ALGOL 60採納了約翰·巴科斯提議的if–then–else條件語句並使之流行起來。Lisp深刻影響了艾倫·凱，他是在Xerox PARC開發Smalltalk的研究組的領導者；反過來Lisp又受到Smalltalk的影響，其後來的方言在1970年代接納了面向物件程式設計特徵，包括有繼承的類、封裝的例項、訊息傳遞等。物件系統介入了多重繼承和混入的概念。Common Lisp物件系統提供了多重繼承、具有多分派的多方法、和頭等泛化函式，從而產生了一種靈活而強力形式的動態分派。CLOS充當了很多後來的包括Scheme在內的Lisp的物件系統的模板，它經常透過等人發展出的元物件協議來實現，這是一種反射式元迴圈設計，其中的物件系統依據自身來定義。由於這些特徵的融合，Lisp成為Smalltalk之後第二個具有元物件系統的語言。多年以後艾倫·凱宣稱，只有Smalltalk和Lisp可以視為完全意義上的面向物件程式設計系統。Lisp介入了自動垃圾回收的概念，即系統巡視堆來尋找無用的記憶體。現代複雜的垃圾回收演算法比如分代垃圾回收的進步，受到了它在Lisp中使用的激勵。艾茲赫爾·戴克斯特拉在他的1972年圖靈獎演講中說道：很大程度上由於它對於包括早期微處理器在內的早期計算機硬體的資源需求，Lisp未能像Fortran和ALGOL後裔C語言那樣在人工智慧社群之外得以流行。由於它適合於複雜和動態的應用，Lisp在2010年代享有了一定程度的大眾關注的復興。七個原始運算.保羅·格雷厄姆從約翰·麥卡錫的最初論文中提煉出如下7個原始運算：quote.codice_66返回codice_10，通常簡記為codice_68：AA將codice_6寫成codice_70只是一種語法糖。atom.codice_71當codice_10是一個codice_23或者空的codice_74時返回原子codice_75，否則返回codice_76。在Common Lisp中通常習慣用原子codice_75列表示真，而用空列表codice_78或codice_76列表示假。例如：TNILTcodice_23是需要求出實際引數值的算符，下面展示codice_6算符的作用，即透過引述一個列表，避免它被求值。一個未被引述的列表達式作為實際引數，codice_23會將其視為程式碼，例如：T這是因為codice_84已求值出結果codice_75，把它代入codice_86，成為codice_87，從而這個列表達式的結果是codice_75。反之一個被引述的列表，僅僅被視為列表，例如：NIL引用看上去有些奇怪，因為很難在其它語言中找到類似的概念，但正是這一特徵構成了Lisp最為與眾不同的特點：程式碼和資料使用相同的結構來列表示，只是用codice_6來區分它們。eq.codice_90當codice_10和codice_92指向相同的物件的時候返回codice_75，否則返回codice_76，例如：TNILTNIL值得注意的是在Common Lisp中，原子物件在記憶體中只會有一份複製，所以codice_95返回codice_75。car.codice_97要求codice_10是一個列表，它返回codice_10中的第一個元素，例如：Acdr.codice_100同樣要求codice_10是一個列表，它返回codice_10中除第一個元素之外的所有元素組成的列表，例如：cons.codice_103預期codice_92的值是一個列表，並且返回包含codice_10的值和隨後codice_92的值的那些元素的一個列表，例如：cond.codice_107的求值規則如下：對“條件列表達式codice_108”依次求值，直到有一個返回codice_75。如果能找到這樣的codice_108列表達式，相應的“結果列表達式codice_111”的值，作為整個codice_65列表達式的返回值。例如：SECOND物件系統.已經有各種物件系統和模型建造在Lisp之上、旁邊或其中，包括：範例.Hello World!這個Hello World!例子展示Lisp的三種主要方言，在基本輸出和函式定義上的用法：階乘.Lisp語法自然的適合於遞迴。數學問題比如遞迴定義集合的列舉，在這種表示法中表達是很容易的。例如，要求值一個數的階乘：(if (zerop n) 1(* n (factorial (1- n)))))下面的版本在底層Lisp系統進行尾遞迴最佳化時比前面版本取用更少的堆疊空間：(if (zerop n) acc(factorial (1- n) (* acc n))))對比上述例子，下面的指令式版本使用了Common Lisp的宏：(loop for i from 1 to nfor fac = 1 then (* fac i)finally (return fac)))反轉列表.下列函式反轉一個列表。它與Lisp內建的codice_113函式做同樣的事情：(let ((return-value))(dolist (e list) (push e return-value))return-value))