3. 序言


小技巧

为了庆祝Scheme的20周年纪念,我们第三次修订了 The Little LISPer

给了它一个更加准确的名字 The Little Schemer

并且写了一本它的续篇 The Seasoned Schemer

程序接收和产生数据。设计一个程序需要对处理的数据有透彻的了解。一个好的程序同样也会反映出它所处理的数据的结构。大部分的数据及程序都是递归形式的。递归是一种通过自己定义自己,或者自己调用自己来求解问题的行为。

本书的目标是教会读者递归思想 。首先一个任务就是决定哪一种语言阐述这种概念。这里有三个明显的选择:自然语言,比如英语;严谨的数学表达式;或者程序语言。自然语言模棱两可,不够准确,甚至冗长。这些在日常交流中自然语言的优势,在介绍递归这样精细的概念时却变成了劣势。数学表达式恰恰相反,它可以用极少的符号表达出一个复杂的概念。遗憾地是,数学表达往往晦涩难懂,只有经过专门的学习才能领会。技术和数学的结合给了我们一个更理想的选择──程序语言。我们相信,程序语言是解释递归这一概念的最佳媒介。它继承了数学的简明,但与之不同的是,我们可以运行代码来观察它们的行为,并通过不断地修改来评估这些改动带来的影响。

Scheme也许是最适合教授递归的程序语言了。从Scheme一诞生就支持符号(计算)。程序员不必考虑他自己的语言符号和这些符号在计算机中如何表示。Scheme最根本的进行计算方法就是递归。编程最主要的工作就是找出(内在的)递归定义。大多数Scheme实现都采用交互的方式(译者:REPL)──程序员能立即感知程序的行为并进行调整。当你读完这本书,最大的感触可能是,Scheme程序和它要处理的数据存在着直接的对应。

虽然Scheme很严谨,但理解Scheme并不需要经过专门的数学训练。实际上, The Little Schemer 出自一门为期两周的Scheme导论课的授课提纲,这门课是专门为没接触过编程,对数学又没有丝毫兴趣的学生开设的。这些学生大多准备从事公共事务方面的职业。我们的理念是“用Scheme递归地写出程序,关键是要识别出模式”。我们关注的是如何用递归的方式编程,因此我们只需用到Scheme中很小的一部分功能:car, cdr, cons, eq?, null?, zero?, add1, sub1, number?, and, or, quote, lambda, define, cond。事实上,这就够了。

The Little SchemerThe Seasoned Schemer 不会向你介绍怎么完成现实世界中的任务,但掌握这两本书中的概念将有助于你更好地理解计算的本质。

3.1. 读者须知

读者应该能轻松地阅读英语,识数和计数。

小技巧

四级就够用了。

3.2. 致谢

感谢一堆人,暂不翻译。

3.3. 给读者的建议

不要囫囵吞枣地阅读本书,仔细地阅读它。书里散落着很多有用的提示。至少阅读本书三次。按章节顺序读。如果你没有完全读懂前一章,那么下一章可能更不懂。每章节的难度是递增的,如果你不能解决前面的问题,那么后面的问题会更让你无处下手。

本书是以一种你与我们之间的对话形式来展开的,对话的内容是一些有趣的Scheme编程例子。当你在阅读本书时,希望你能够尽量尝试运行那些例子。Scheme程序很容易读懂。虽然在不同的Scheme实现之间有一些细微的语法差别(主要是个别名字的拼写和某些函数的作用域稍有不同),但Scheme基本上是一致的。要运行书中的Scheme代码,你还需要定义atom?, sub1, add1.这些函数我们都会在书里详细介绍:

(define atom?
  (lambda (x)
    (and (not (pair? x)) (not (null? x)))))

要想知道你的Scheme有没有正确地定义atom?,运行 (atom? (quote())) ,看是否返回#f。事实上,这个测试也适用于现代的Lisp版本,如Common Lisp。如果用你想使用Lisp,你需要添加atom?函数:

(defun atom? (x)
  (not (listp x)))

你可能需要稍稍修改这程序。书中提供的例子可能都需要做一些修改。在书中,我会在旁注里注明在不同Scheme实现的一些特性。“S:”表示Scheme,“L:”表示Common Lisp。

在第四章,我们会深入探讨三个基本的算术操作:add1, sub1, zero?。虽然Scheme没有提供add1和sub1,但你可以用内置的加减运算符来定义它们。为了避免逻辑上的死结,我们用另一套符号来表示基本的加减操作:+, -。

我们不会在书中给出任何标准的定义。我们相信你能自己搞出一套来,这样比我们给你一个写好的定义更能让你记住、理解它们。请好好消化十诫和五律。学习Scheme的关键是 模式识别 。十诫就是对你所见过的模式的总结。书一开始会简化一些概念。但随后,它们会被不断扩展、丰富。你应该知道,这本书里的所有东西都是Scheme,Scheme是一门通用编程语言,不是这样一本导论性质的书能讲清的。在你掌握了本书之后,你可以去阅读和理解一些进阶的有关Scheme的书了。

我们编写本书时遵循一些约定。不同类别符号的字型稍有不同。

注解

主要的规定就是通过字体来标识不同类型的单词。

该段下面基本就是告诉你各种类型的单词使用什么字体,

这个也不翻译了,看例子就知道。

最后谈一谈断句。Webster把断句定义为用标准的符号分割句子来使文意更明确的行为。有时为了表达清楚,我们会使用非常规的断句方式。注意我们不会对左栏的文字(译注:书采用对话形式,分为左右两栏)断句,因为那是程序语言。

本书的例子中出现食物名有两个原因。

  1. 食物比起那些抽象的符号来说更容易可视化

    (但是在你节食的时候读本书可不是一个好主意)。

    我们希望我们选择食物名能够有助读者理解本书中的例子和主题。

  2. 我们希望在读书时能够小分一下心。

    我们知道当你试图理解这些主题时多少有点沮丧,

    但是一丢丢分心多少能够帮助你远离沮丧的情绪。

你现在要准备开始本书之旅了。祝你好运!我们希望你能够享受在接下来的章节里的挑战。

注解

本篇翻译大部分参考了Sedgewick的 The Little Schemer ── 小众Schemer?