#前言：

在旧的模式中，错误永远不应该出现。事前辛苦订出缜密的规格说明，确保程序完美的运行。理论上听起来不错。不幸地，规格说明是人写的，也是人来实现的。实际上结果是， *规划-然后-实现* 模型不太有效。

几乎所有的程序，都可以从订作适合自己所需的语言中受益。然而越复杂的程序，由下而上的程序设计就显得越有价值。一个由下而上所设计出来的程序，可写成一系列的层，每层担任上一层的程序语言。你可以用任何语言由下而上地设计程序，但 Lisp 是本质上最适合这种方法的工具。

由下而上的编程方法，也是得到可重用软件的最好方法。写可重用软件的本质是把共同的地方从细节中分离出来，而由下而上的编程方法本质地创造这种分离。与其努力撰写一个庞大的应用，不如努力创造一个语言，用相对小的努力在这语言上撰写你的应用。和应用相关的特性集中在最上层，以下的层可以组成一个适合这种应用的语言 ── 还有什么比程序语言更具可重用性的呢？

Lisp 表示法另一个美丽的地方是：它就是如此简单。所有的 Lisp 表达式，要么是 1 这样的数原子，要么是包在括号里，由零个或多个表达式所构成的列表。以下是合法的 Lisp 表达式：

LISP 表达式称为符号表达式或 s 表达式。

s 表达式由三个有效对象、原子、列表和字符串组成。

在 LISP 中，变量没有类型，但数据对象有类型。

 

任何 s 表达式都是有效的程序。

LISP 程序运行在**interpreter**或者作为**compiled code.**

解释器在重复循环中检查源代码，这也称为读取-评估-打印循环 (REPL)。它读取程序代码、对其求值并打印程序返回的值。

LISP 使用前缀表示法

你可能已经注意到 LISP 使用**prefix notation.**

在上面的程序中，+ 符号用作数字求和过程的函数名称。

在前缀表示法中，运算符写在它们的操作数之前。例如，表达式，

- LISP 程序的评估

LISP 程序的评估有两个部分 -

- 阅读器程序将程序文本翻译成 Lisp 对象

- 通过评估程序根据这些对象实现语言的语义

评估过程采取以下步骤 -

- 阅读器将字符串翻译成 LISP 对象或**s-expressions.**

- 求值器定义 Lisp 的语法**forms**是从 s 表达式构建的。第二级评估定义了一种语法，用于确定哪个**s-expressions**是 LISP 形式。

- 评估器作为一个函数工作，它将有效的 LISP 形式作为参数并返回一个值。这就是我们将 LISP 表达式放在括号中的原因，因为我们将整个表达式/形式作为参数发送给计算器。所有的 Lisp 表达式，要么是 1 这样的数原子，要么是包在括号里，由零个或多个表达式所构成的列表。LISP程序由三个基本构建块组成 −

- atom
- list
- string

**atom** 是一个连续字符的数字或字符串。它包括数字和特殊字符

**list** 是一个原子序列和/或括号中的其他列表。

**string** 是一组用双引号括起来的字符。

分号符号（；）用于指示注释行。

整数与字符串一样，都是对自身求值的。

以下是需要注意的一些要点 −

- LISP中的基本数字运算是+、-、*和/
- LISP 将函数调用 f(x) 表示为 (fx)，例如 cos(45) 写为 cos 45
- LISP 表达式不区分大小写，cos 45 或 COS 45 相同。
- LISP 试图评估一切，包括函数的参数。只有三种类型的元素是常量，总是返回自己的值

- 数字

- 这封信**t,**那代表逻辑真。

- 价值**nil,**这代表逻辑错误，以及一个空列表。

**LISP - 数据类型**



简述

在 LISP 中，变量没有类型，但数据对象有类型。

LISP 数据类型可以分类为。

- **标量类型**− 例如，数字类型、字符、符号等。

- **数据结构**− 例如，列表、向量、位向量和字符串。

**1. 标量类型（Scalar Types）**

标量类型是指**单一的、不可再分**的值。它们通常用于表示简单的数据。

**特点：**

- **单一值**：每个标量类型变量或对象只存储一个值。
- **不可变**：大多数标量类型是不可变的（immutable），即它们的值不能被修改。
- **直接操作**：标量类型通常用于直接计算或比较。

**2. 数据结构（Data Structures）**

数据结构是指**可以存储多个值**的复合类型。它们通常用于组织和管理复杂的数据。

**特点：**

- **复合值**：数据结构可以存储多个值，甚至可以是其他数据结构。
- **可变性**：某些数据结构是可变的（mutable），例如列表和哈希表；而某些是不可变的，例如字符串（在某些     Lisp 实现中）。
- **复杂操作**：数据结构通常用于存储和操作一组数据，支持插入、删除、遍历等操作。

 

**或者是**

**1. 基本数据类型**

这些是 Lisp 中最基础的数据类型：

- **整数（Integer）**：例如 10、-5。
- **浮点数（Float）**：例如 3.14、-0.001。
- **字符（Character）**：例如 #\a、#\b。
- **字符串（String）**：例如 "hello"。
- **符号（Symbol）**：例如 'hello、'x。*符号*是英语的单词 (words)。无论你怎么输入，通常会被转换为大写：
- \> 'Artichoke
- ARTICHOKE
- 符号（通常）不对自身求值，所以要是想引用符号，应该像上例那样用 ' 引用它。
- **布尔值（Boolean）**：在 Lisp 中通常用 t 表示真，nil 表示假。



**2. 复合数据类型**

这些数据类型可以存储多个值：

- **列表（List）**：例如 '(1 2 3)、'(a b c)。*列表*是由被括号包住的零个或多个元素来表示。元素可以是任何类型，包含列表本身。使用列表必须要引用，不然 Lisp 会以为这是个函数调用；
- 你可以调用 list 来创建列表。由于 list 是函数，所以它的实参会被求值。这里我们看一个在函数 list 调用里面，调用 + 函数的例子：
- 注意引号保护了整个表达式（包含内部的子表达式）被求值。
- **向量（Vector）**：例如 #(1 2 3)。
- **数组（Array）**：例如多维数组。
- **哈希表（Hash Table）**：例如键值对的集合。
- **结构体（Structure）**：用户定义的复合数据类型。

 

任何变量都可以将任何 LISP 对象作为其值，除非您明确声明了它。

虽然没有必要为 LISP 变量指定数据类型，但是它有助于某些循环扩展、方法声明和我们将在后面的章节中讨论的其他一些情况。

数据类型排列成层次结构。数据类型是一组 LISP 对象，许多对象可能属于一个这样的集合。

这**typep**谓词用于查找对象是否属于特定类型。

这**type-of**函数返回给定对象的数据类型。

在表达式 (+ 2 3) 里， + 称为操作符，而数字 2 跟 3 称为实参。

在日常生活中，我们会把表达式写作 2 + 3 ，但在 Lisp 里，我们把 + 操作符写在前面，接着写实参，再把整个表达式用一对括号包起来： (+ 2 3)

 

日常生活中用 + 时，它必须有两个实参，一个在左，一个在右。前序表示法的灵活性代表着，在 Lisp 里， + 可以接受任意数量的实参，包含了没有实参：

一个不遵守 Common Lisp 求值规则的操作符是 quote 。 quote 是一个特殊的操作符，意味着它自己有一套特别的求值规则。这个规则就是：什么也不做。 quote 操作符接受一个实参，并完封不动地返回它。

\> (**quote** (+ 3 5))

(+ 3 5)

为了方便起见，Common Lisp 定义 ' 作为 quote 的缩写。你可以在任何的表达式前，贴上一个 ' ，与调用 quote 是同样的效果：

在 Lisp 里， + 是函数，然而如 (+ 2 3) 的表达式，是函数调用。

当 Lisp 对函数调用求值时，它做下列两个步骤：

1. 首先从左至右对实参求值。在这个例子当中，实参对自身求值，所以实参的值分别是 2 跟 3 。
2. 实参的值传入以操作符命名的函数。在这个例子当中，将 2 跟 3 传给 + 函数，返回 5 。

 