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"