Peter Norvig 那篇《How to Write a Lisp Interpreter in Python》最容易被误读成炫技:用很少 Python 代码写一个 Lisp。

我更在意的不是代码短,而是它把解释器这件事拆得很干净:program → parse → AST → eval → result。一个程序先变成结构,再按规则求值。计算机没有念咒,语言也没有神秘主义。

这篇教程的对象也很明确:有编程基础,但没系统学过解释器、编译器的人。你不需要先啃厚书,先看懂 Lispy,很多语言特性会从“语法记忆题”变成“规则理解题”。

Lispy 做了什么:把解释器压成一条短链路

Norvig 的目标很克制:用 Python 3 简洁实现一个 Scheme 方言解释器,名字叫 Lispy。

它不是完整工业级 Scheme。它省略了不少语言细节,也不靠性能说话。它是教学解释器,强在概念压缩。

核心部件就这几块:

部件作用读者该看什么
Parsing把字符切成 token,再组装成抽象语法树程序文本如何变成结构
Environment保存变量名到值的绑定名字为什么能找到值
eval按语义规则执行表达式程序含义由谁决定
REPL读入、求值、打印、循环Lisp 的交互式工作方式

一个例子足够说明问题:

(begin (define r 10) ( pi ( r r)))

解析后大致变成:

['begin', ['define', 'r', 10], ['', 'pi', ['', 'r', 'r']]]

再交给 eval,得到:

314.1592653589793

这是半径 10 的圆面积。链路很短:Parsing 把字符变成抽象语法树,Execution / eval 按语义规则执行。看懂这一步,解释器就不再是黑箱。

对开发者的直接影响也在这里。

如果你写了几年 Python、JavaScript 或 Java,却总觉得“语言特性很多但背后没串起来”,Lispy 值得按代码走一遍。重点不是记 Lisp 语法,而是盯住三处:parse 怎么造树,环境怎么查名字,eval 怎么分派不同表达式。

如果你对编程语言设计、Lisp/Scheme、计算机基础感兴趣,动作更简单:先跑通这个圆面积例子,再改一个小语法或小内置函数。别急着做大。先确认自己真的理解了求值路径。

Scheme 的括号不是梗,是结构裸露

很多人第一次看 Lisp/Scheme,会先盯着括号。这个反应正常,但容易看偏。

Norvig 借 Scheme 讲的不是“括号很多”,而是“语法足够一致”。Scheme 的核心形式很少:原子表达式、列表表达式、ifdefine、过程调用等。

规则也很直接。数字求值为自己。符号去环境里查值。列表的第一个元素决定后面怎么解释。遇到特殊形式,就按特殊规则;遇到普通过程,就先求值参数再调用。

和 Python、Java 这类语言相比,Scheme 少了很多表面语法:中缀运算符、点号、逗号、分号、多种括号、优先级规则。它的代价是括号显眼,收益是结构清楚。

这个对比很关键。

现代语言常把门面做得舒服。语法糖多,工具提示好,很多复杂性被藏起来。Scheme 反着来,把骨架露出来。你未必喜欢它,但它很适合教学,因为遮挡少。

限制也要说清。Lispy 不能替代严肃的编译原理课程,也不能代表完整 Scheme 工程能力。它给的是一张骨架图,不是一台生产机器。

所以,读这篇教程最该避免两种误会:一种是把它当“90 行代码征服编译器”;另一种是嫌它太小,就低估它。小不是问题。问题是它小得刚好能让人看见关键部件。

真正该补的课:eval 决定语言的边界

Steve Yegge 有句老话:“If you don't know how compilers work, then you don't know how computers work.” 如果你不知道编译器如何工作,你就不知道计算机如何工作。

放到 Lispy 上,这句话不用理解得太重。它不是要求每个程序员都去写生产级编译器。它提醒的是:代码被语言接管之后,到底发生了什么,你至少要有一张粗地图。

if 为什么不会先把两个分支都算完?因为它是特殊形式。

变量为什么能指向值?因为环境里有绑定。

函数调用为什么通常要先算参数?因为 eval 采用了这套求值规则。

所谓语言特性,很多时候就是这些规则的组合、例外和边界。语法只是入口,求值规则才是骨架。

这也是 Norvig 这篇教程比许多厚教材锋利的地方。它没有把读者困在术语里,而是直接摆出一门语言最小可运行的分工:谁解析,谁绑定,谁求值,谁能改变默认执行顺序。

扯远一点,编程语言史里反复出现同一个场景:新语言总说自己让人更自由,最后真正塑造开发者行为的,往往是求值模型、类型系统、包管理、运行时和工具链。

“天下熙熙,皆为利来。”这句话放在语言世界里也不突兀。简洁、效率、安全、生态,都有收益,也都有代价。Lispy 的好处,是让这些代价不再躲在宣传词后面。

接下来最该观察的不是 Lispy 能不能变成什么大项目。它本来就不是这个方向。

更该观察的是:你读完后,能不能解释一段代码为什么按这个顺序运行;能不能说清变量从哪里来;能不能指出一个语法糖背后省掉了哪条规则。能做到这些,它的教学目的就已经完成。

别把 Lispy 当成“Python 写 Lisp”的小玩具。它更像一张透明底片。拿它照一下,很多语言的漂亮外壳会淡下去,剩下规则、代价和边界。