从顺序计算到条件选择
本节阅读量:写第三章代码之前,先把新增语义说清楚。
第三章加入:
|
|
程序仍然是一个表达式,每个表达式仍然产生一个整数结果。
用整数表示条件是否成立
本章不另外加入布尔值,直接用整数表示条件是否成立:
|
|
eq? 只会返回 0 或 1,if 则根据结果是否为 0 选择分支。
这类用来提问、并返回成立或不成立的表达式,通常叫做谓词表达式。这里的“谓词”不是新的值类型,只是对 eq? 这类表达式的称呼:它仍然返回整数,只是结果固定为 0 或 1。
eq? 判断两个结果是否相等
eq? 会先求值左边表达式,再求值右边表达式,然后比较两个结果:
|
|
左右结果都是 42,所以返回 1。
|
|
左右结果不同,所以返回 0。
判断某个表达式是否等于零也用 eq? 表达:
|
|
因为 (+ 1 -1) 的结果是 0,所以整个表达式返回 1。
if 只选择一个分支
if 的形式是:
|
|
求值顺序是:
|
|
例如:
|
|
condition 得到 1,因此结果是 then 分支的 42。
|
|
condition 得到 0,因此结果是 else 分支的 42。
if 的条件不一定来自谓词。只要结果不是 0,就会选择 then 分支:
|
|
if 自己也是表达式,它的结果就是被选中分支的结果。因此 then 和 else 可以返回任意整数表达式,不要求只能返回 0 或 1。
“只求值一个分支”是语言语义的一部分,不只是解释器碰巧采用的写法。实现编译器时,两边的代码都要生成,但程序每次运行只允许进入其中一边。
这不表示未选中的分支可以随意写错。parser 仍然要读懂两个分支,lowerer 也会遍历两边并解析其中的变量;本章只对语法正确、所有变量引用都有词法绑定的程序比较解释器和编译器行为。对这样的程序,运行时始终只执行被选中的分支。
写成规则
第三章的表达式规则是:
|
|
identifier 仍然沿用第二章的简单规则:一个或多个英文字母。eq? 中的问号属于特殊形式的固定拼写,不表示普通变量名也可以带问号。
合法和非法
合法程序:
|
|
非法程序和原因可以一一对照:
| 程序 | 为什么不合法 |
|---|---|
(eq? 1) |
缺少右边表达式 |
(eq? 1 2 3) |
比较后面多出一个表达式 |
(if 1 42) |
缺少 else 分支 |
(if 1 2 3 4) |
else 后面还有多余内容 |
下一节先看 AST 怎样保存这些结构。