LISP

20世紀

1955年至1956年間，資訊處理語言被創造出來，用於人工智慧處理（早期的基於符號處理的人工智慧領域，以圖靈測試為目標）。此領域中有研究者持有觀點：「符號演算系統可以衍生出智慧型。」。它首先使用了列表(抽象資料類型)與遞迴。
1958年，約翰·麥卡錫在麻省理工學院發明了Lisp程式語言，採用了資訊處理語言的特徵。1960年，他在《ACM通訊》發表論文，名為《遞迴函式的符號表達式以及由機器運算的方式，第一部》（Recursive Functions of Symbolic Expressions and Their Computation by Machine, Part I）。在這篇論文中闡述了只要透過一些簡單的運算子，以及用於函式的記號，就可以建立一個具圖靈完備性語言，可用於演算法中。
麥卡錫最初使用M-表達式寫程式碼，之後再轉成S-表達式，舉例來說M-表達式的語法，car[cons[A,B]]，等同於S-表達式的(car (cons A B))。然而由於S-表達式具備同像性的特性（homoiconic，即程式與資料由同樣的結構儲存），實際應用中一般只使用S-表達式。此外他也借用了資訊處理語言中的許多概念。
約翰·麥卡錫的學生史帝芬·羅素在閱讀完此論文後，認為Lisp程式語言當中的eval函式可以用機器碼來實做。他在IBM 704機器上，寫出了第一個Lisp直譯器。1962年，蒂姆·哈特（Tim Hart）與麥克·萊文（Mike Levin）在麻省理工學院以Lisp程式語言，實做出第一個完整的Lisp編譯器。這兩人在筆記中使用的語法比麥卡錫早期的程式碼更接近現代Lisp風格。
然而使用20世紀70年代當時的編譯器技術和硬體，要實現Lisp還是困難的挑戰。由研究生丹尼爾·愛德華茲所開發的垃圾收集程式，使得在通用電腦上運行Lisp變得實用，但效率仍然是一個問題。這導致了Lisp專用機器的創建：用於運行Lisp環境和程式的專用硬體。之後電腦硬體和編譯器技術的發展迅速，使得昂貴的Lisp專用機器過時。

西元2000年迄今

在20世紀90年代衰退之後，Lisp最近十年來因一些關注而逐漸復甦。大多數新活動都集中在Common Lisp，Clojure，Racket，Scheme和Emacs Lisp的實作上，包括開發新的跨平台函式庫和應用。當其他人認為Lisp已經是過時陳舊的，如保羅·格雷厄姆和埃里克·雷蒙等人繼續出版有關於Lisp編程的著作，一些新的開發人員受到這些作者啟發，經常將Lisp這種語言描述為令人大開眼界的經驗，並聲稱在本質上比較其它程式語言更有生產效率。這種意識的提高可對比於，如同Lisp在90年代中期「人工智慧冬季」的短暫增長。
Dan Weinreb在他的調查中，列出了11個積極維護中的Common Lisp實作。Scieneer Common Lisp是一個新的實作商業化產品，由CMUCL於2002年首次發布。
開源社群建立了新的支援基礎：CLiki是個收集Common Lisp相關資訊的維基，Common Lisp目錄列出了資源，#lisp是一個受歡迎的IRC頻道，可以共用和註釋程式碼片段（在lisppaste的支援下，一個用Lisp編寫的IRC機器人），Planet Lisp收集了各種 Lisp相關部落格的內容，LispForum用戶討論Lisp主題，Lispjobs是個公布職缺機會的服務，還有一個Weekly Lisp News提供每週新聞。Common-lisp.net是開源專案的代管站點。Quicklisp則是含括了許多函式庫的裝載管理器。
Lisp50@OOPSLA慶祝了Lisp的50週年（1958-2008）。在波士頓，溫哥華和漢堡有定期的當地用戶會議。其他活動包括歐洲共同Lisp會議，歐洲Lisp專題討論會和國際Lisp研討會。Scheme社群積極維護了二十多個實作。在過去幾年中已開發了數個有意義的新實作（Chicken，Gambit，Gauche，Ikarus，Larceny，Ypsilon），Scheme社群廣泛接納了R5RS語言標準。Scheme需求實作過程建立了很多預備標準函式庫和Scheme擴展功能。各種 Scheme實作的用戶社群持續地增長。
一個新的語言標準化過程於2003年開始，並在2007年產生了R6RS標準，而使用Scheme介紹電腦科學課程的學校似乎有所減少。麻省理工學院的電腦科學入門課程，已經不再使用Scheme。
有幾種新的Lisp方言：Arc，Hy，Nu，Clojure，Liskell，LFE（Lisp Flavored Erlang）和Racket。

基本介紹

Lisp是第一個函數式程式語言，區別於C語言、Fortran等命令型程式語言和Java、C#、Objective-C等物件導向程式語言。由於歷史的原因，Lisp長期以來被認為主要用於人工智慧領域，但Lisp並不是只為人工智慧而設計，而是一種通用的程式語言。
Lisp的運算式是一個原子（atom）或列表（list），原子又包含符號（symbol）與數值（number）；列表是由零個或多個運算式組成的序列，運算式之間用空格分隔開，放入一對括號中，如：
abc()(abc xyz)(a b (c) d)
最後一個列表是由四個元素構成的，其中第三個元素本身也是一個列表，這種又稱為巢狀列表（nested list）。
正如算數運算式1+1有值2一樣，Lisp中的運算式也有值，如果運算式e得出值v，我們說e返回v。如果一個運算式是一個表，那麼我們把表中的第一個元素叫做運算子，其餘的元素叫做自變數。

基本運算子1 quote

(quote x)返回x，我們簡記為'x
(quote a)
上面的表達式的值是a。如果使用C語言或者Java語言的表達方式，可以說成：上面這段程式碼返回的值是a。
'a
這個表達式和上面的那個相同，值也是a。將quote寫成  ' 只是一種語法糖。
被quote起來的單一個元素會成為符號（symbol，例如'a）。符號是Lisp中的一個特別概念，他在程式碼中看起來是個字串，但並不盡然，因為符號其實會被Lisp直譯器直接指向某個記憶體位置，所以當你比較'apple和'apple兩個符號是否相同時，不需要像字串一樣一個個字元逐字比較，而是直接比較記憶體位置，故速度較快（使用eq運算子來比較，如果使用equal運算子會變成逐字比較）。當你定義一個函式，或者定義一個變數時，他們的內容其實就是指向一個符號。

基本運算子2 atom

(atom x)當x是一個atom或者空的list時返回原子t，否則返回NIL。在Common Lisp中我們習慣用原子t表示真，而用空表()或NIL表示假。
> (atom 'a)t> (atom '(a b c))NIL> (atom '())t
現在我們有了第一個需要求出自變數值的運算子，讓我們來看看quote運算子的作用——通過參照（quote）一個表，我們避免它被求值（eval）。一個未被參照的運算式作為自變數，atom將其視為程式碼，例如：
> (atom (atom 'a))t
這是因為(atom 'a)的結果（t）被求出，並代入(atom (atom 'a))，成為(atom t)，而這個運算式的結果是t。
反之一個被參照的表僅僅被視為表
> (atom '(atom 'a))NIL
參照看上去有些奇怪，因為你很難在其它語言中找到類似的概念，但正是這一特徵構成了Lisp最為與眾不同的特點：程式碼和資料使用相同的結構來表示，只用quote來區分它們。

基本運算子3 eq

(eq x y)當x和y指向相同的物件的時候返回t，否則返回NIL，值得注意的是在Common Lisp中，原子物件在記憶體中只會有一份拷貝，所以(eq 'a 'a)返回t，例如：
>(eq 'a 'a)t>(eq 'a 'b)NIL> (eq '() '())t> (eq '(a b c) '(a b c))NIL

基本運算子4 car

Contents of the Address part of Register number縮寫
(car x)要求x是一個表，它返回x中的第一個元素，例如：
> (car '(a b))a

基本運算子5 cdr

(cdr x)同樣要求x是一個表，它返回x中除第一個元素之外的所有元素組成的表，例如：
> (cdr '(a b c))(b c)

基本運算子6 cons

(cons x y)返回一個cons cell(x y)，如果y不是一個list，將會以dotted pair形式展現這個cons cell，例如：
>(cons 'a 'b)(a . b)
一個cons cell的第二項如果是另一個cons cell，就表示成表的形式，例如：
 (cons 'a (cons 'b 'c))
就表示成
（a b . c）
若一個cons cell第二項為空，就省略不寫，例如：
 (cons 'a  (cons 'b ()))
表示為
（a b）
這樣，多重的cons cell就構成了表：
> (cons 'a (cons 'b (cons 'c ())))(a b c)

基本運算子7 cond

(cond (p₁ e₁) ...(pₙ eₙ))的求值規則如下。對「條件運算式p」依次求值直到有一個返回t.如果能找到這樣的p運算式，相應的「結果運算式e」的值作為整個cond運算式的返回值。
> (cond ((eq 'a 'b) 'first)  ((atom 'a)  'second))
 second

函式

七個原始運算子中，除了quote與cond，其他五個原始運算子總會對其自變數求值。我們稱這樣的運算子為函式。

Scheme

(display "Hello, world!");; 在屏幕中打印出：Hello, world!;; 函数定义(define (hello)
  (display "Hello, world!"))
 
;; 函数调用(hello);; 在屏幕中打印出：Hello, world!

Common Lisp

(format t "hello, world!");; 在屏幕中打印出：hello, world!;; 函数定义：(defun hello-world ()
  (format t "hello, world!"));; 调用函数：(hello-world);; 在屏幕中打印出：hello, world!;; 并以NIL作为函数的返回值

Clojure

(print "hello, world!");; 在屏幕中打印出：hello, world!;; 函数定义：(defn hello-world []
  (print "hello, world!"));; 调用函数：(hello-world);; 在屏幕中打印出：hello, world!;; 并以nil作为函数的返回值

Lisp的巨集

Lisp的語法結構使資料與程式只是一線之隔（有quote就是資料，沒quote就是程式）。由於Lisp這種「資料即程式、程式即資料」的概念，使Lisp的巨集（Macro）變得非常有彈性：你可以定義巨集，指定它應該被編譯器翻譯（巨集展開）成什麼程式，程式和資料都可以靈活地互相轉換，最後展開的程式碼會成為整個程式的一部分。巨集的實現非常倚重quote來達成。當你定義了一個巨集，巨集被quote的部份會先被編譯器unquote，而沒有quote、或已經被unquote的部份，則會先被求值。最終編譯器生成的整個程式碼才是最後執行時的程式碼。以下以廣泛使用的Emacs Lisp為範例（以下範例亦相容Common Lisp），解釋最基本的Lisp巨集。
想要建立一個list並賦予給fruit這個變數時不能這樣做，因為這個list沒有被quote過，會被編譯器視為「程式」執行（會把"apple"這個字串當成函式解釋），而不是「資料」，因而產生錯誤：
> (setq fruit ("apple" "banana" "citrus"))錯誤："apple"不是一個有效函數。
但這樣就正確了：
> (setq fruit (quote ("apple" "banana" "citrus")))("apple" "banana" "citrus");;或者> (setq fruit '("apple" "banana" "citrus"))("apple" "banana" "citrus");;也可以用(list...)運算子，這樣一樣可以建立list。因為list本身是個函數，本來就應該被當成程式執行而不是資料，所以不會報錯：> (setq fruit (list "apple" "banana" "citrus"))("apple" "banana" "citrus")
前面有提到使用'符號這個語法糖能夠代替quote，但還有另外一種符號是`，意義基本上與'相同，但被`包起來的部份可以再用來unquote；而'沒有這種能力。
也就是說被`給quote起來的部份是資料，但使用逗號「,」來unquote，令被quote的資料變回程式。（注意quote只有一個arg，所以arg要用list包起來）
;;使用`來quote整個list> `("apple" "banana" "citrus")("apple" "banana" "citrus");;使用逗號，來unquote，這樣fruit這個變量會被重新求值。> `("apple" "banana" "citrus" ,fruit)("apple" "banana" "citrus" ("apple" "banana" "citrus"));;可以利用unquote的特性，定義一個函数，讓該函数根據輸入的參數回傳一個我們想要的list数据結構：(defun user-profile (name email mobile)
  `((name . ,name)
    (email . ,email)
    (mobile . ,mobile)))(user-profile "Richard" "rms@gnu.org" "Noooo!")=> ((name . "Richard")
    (email . "rms@gnu.org")
    (mobile . "Noooo!"))

簡易巨集範例

這裡定義一個巨集叫做nonsense，這個巨集可以方便地定義更多以nonsense為開頭的新函式：
(defmacro nonsense (function-name)
  `(defun ,(intern (concat "nonsense-" function-name)) (input) ;intern可以將string轉成symbol
     (print (concat ,function-name input))));;解釋：;;這個巨集在編譯時，`(defun  因為被quote所以不會被求值，;;但裡面的,(intern ...)這一段從逗號開始，整個括號括起來的;; s-expression部份會被求值。這時作為argument輸入的function-name;;就是在這時被插進macro中。其餘剩下的部份因為仍然在`(defun的quote;;影響之下，並不會被求值。;;現在巨集展開完了，整個巨集才被當成一般function執行。
 
(nonsense "apple")  ;使用我們剛剛定義的nonsense這個macro來定義新的f函数=> nonsense-apple  ;成功定義出了新的函数叫做nonsense-apple(nonsense "banana")  ;再使用一次巨集來定義新的函数叫做nonsense-banana=> nonsense-banana  ;成功定義了新的函数。(nonsense-apple " is good")  ;使用剛剛定義出的新函数=> "apple is good"(nonsense-banana " I love to eat")  ;使用另一個剛剛定義函数=> "banana I love to eat"