# 什么是程序

#### 鱼和渔 (Declarative Knowledge and Imperative Knowledge)

Declarative Knowledge 是指正确的知识，而 Imperative Knowledge 指的是能够获取一类 Declarative Knowledge 的步骤。这与我们的俗语 “授人以鱼不如授人以渔” 中的鱼和渔暗合。再举一例，小学时背诵的乘法口诀表，就是 Declarative Knowledge，它让我们熟记 81 种一位数乘法的结果；而小学学习的乘法竖式计算法，就是 Imperative Knowledge，它让我们拥有计算任意整数之间的乘法结果。我们的记忆有限，无法在脑海中记诵无穷多种整数相乘的结果，但 Imperative Knowledge 能够让我们按需产生 Declarative Knowledge，简直完美。讲了这么多，其实就是想引出：

**Imperative Knowledge, 即获取一类 Declarative Knowldge 的步骤，被称为程序 — procedure；而计算机内部实际按照程序执行的步骤，成为进程 — process。**

#### 描述程序 (计算机语言) 的要素

我们用自然语言与人交流，与计算机交流同样需要语言。对比自然语言，计算机语言拥有以下构成要素：

1. 词典 (vocabulary)：对应汉语字词，英语单词，计算机语言通常也有一定的保留词语 (reserved keywords)，比如：int, double, char, boolean 等等，这些词语是我们描述程序的基础。
2. 语法 (syntax)：有了汉语字词，但如果我们随意拼接这些字词，就无法准确描述意图，如：吗思意我懂你。词典中的字词按一定**方法**组合起来，才能有效表明意图，这里的方法即指为**语法**。
3. 语义 (semantics)：语义指的是在解释程序时的一套规则，语义层在合乎语法的程序与最终程序的执行方法之间。

#### 描述程序的目的

描述程序的真实目的是**控制大型系统的复杂性**。为了要达到这个目的，通常我们会递归地重复下面的过程：

1. 创建一些语言的原始元素 (primitives) — 简单的数据和程序 (simple data and sinple procedures)
2. 创建组合语言元素的方法 (means of combination)
3. 创建抽象语言元素的规则 (means of abstraction) — 把利用原始元素构造出来的语言元素看作是新的原始元素，忽略其内部细节，以此为基础继续构造更抽象的语言元素。

为什么通过这种方式可以帮助我们实现控制大型系统的复杂性呢？

我们以烹饪为例，如果让一个厨师回到远古时代，没有油盐酱醋，那么他可能需要掌握：

* 生火技术
* 植物油提取技术
* 晒盐技术
* 黄豆种植及酱油提取技术
* 大米种植及醋的酿造技术

如果烹饪是一个大型系统，以上这些技术就是原始元素，而对应的 火、油、盐、酱、醋则是这些原始元素抽象出来的高级原始元素，当这些元素被抽象出来后，厨师就可以只需要掌握如何利用这些高级原始元素进行烹饪的技术，减少他所需掌握的技术以及工作量。而常人就可以使用抽象程度更高的老干妈，甚至酸菜鱼酱料包等等元素，轻松烹饪复杂菜品。

#### 控制系统复杂性的工具

1. 抽象 (Abstraction)：利用简单元素构建复杂元素，同时对使用者隐藏背后的实现细节。
2. 标准接口 (Conventional interfaces) 和编程范式 (Programming paradigms)：二者为我们提供将不同组件结合起来的方式。
3. 元语言抽象 (Meta-linguistic abstraction)：为特定问题设计新的语言。

**有了可以执行的程序还需要有实体真正去执行，它就是计算机。那程序与计算机之间是如何沟通呢？**

#### 从比特 (bit) 到原始对象 (primitive objects)

要与计算机交流，我们需要知道如何表达信息 (information representation) — 数字和符号。

**数字表达**

计算机通过区分高低电压来表达基本信息，因此表达数字最原始的方法就是使用二进制变量，0或1，这个变量可以表达 1 比特信息。通过将比特组合成字节 (byte) 和字 (word)，我们可以表达更大的数字。通过符号位，我们可以表达正负数，通过指数位，我们可以表达小数。

**符号表达**

我们不仅可以使用比特的组合表达数字，也可以用它们来编码符号。

尽管我们可以仅仅依靠比特来表达程序，但这种方式像结绳计数一般过于低级，严重降低表达效率，因此我们需要**抽象**的帮助 — 假设我们已经拥有一些原始对象 （基本数据结构），以及对这些对象的一些基本操作，然后利用它们来构造表达程序。它们一般包括：数字 (Numbers)、字符 (Characters) 和布尔 (Booleans)。

#### Scheme 表达式的评价规则 (Rules for evaluation)

1. 自评价 (self-evaluating) 表达式：返回自评价值
2. 名字 (name) 表达式：返回环境中与之绑定的值
3. 特殊形式 (special form) 表达式：依照特殊规则进行评价
4. 组合 (combination) 表达式:
   * 评价所有子表达式 （顺序不定)
   * 对子表达式评价结果执行操作后返回结果

#### 参考

[Youtube: MIT6.001-SICP-2004-lecture-1](https://www.youtube.com/watch?v=FIUJd_ZFmGo\&t=2s\&list=PL7BcsI5ueSNFPCEisbaoQ0kXIDX9rR5FF\&index=1)

[MIT6.006-SICP-2005-lecture-notes-1](https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-001-structure-and-interpretation-of-computer-programs-spring-2005/lecture-notes/lecture1webhand.pdf)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://zhenghe.gitbook.io/open-courses/mit-6.001-sicp/shen-me-shi-cheng-xu.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
