“SECD 抽象机把函数求值拆成四类状态:已经算出的值放在 Stack,变量的词法绑定放在 Environment,接下来要执行的指令放在 Control,被函数调用暂时中断的现场放在 Dum…”
形式陈述
环境通常记为
扩展
因此扩展会遮蔽
直觉
环境把“这个名字在这里代表什么”从语法之外的默契变成显式对象。源代码里可以在不同嵌套层重复使用同一个名字,求值器只要沿当前环境查找,就能找到最近且未被遮蔽的绑定。这种表示也让作用域切换成为普通数据操作:进入 let 或函数体时扩展环境,离开时恢复原环境,而不是在整段程序文本中替换名字。
词法作用域的关键是函数体的自由变量由定义位置决定。求值
当前调用栈可以帮助实现环境,但二者不是同一概念:栈记录动态控制过程,词法环境表达静态嵌套所确定的名字关系。函数返回后闭包仍可能存活,因此它需要的绑定不能因定义时的栈帧退出就一并失效。
例子与边界
考虑 let x = 1 in let x = 2 in x + 3。求值外层绑定后得到 x + 3 在
在 let x = 1 in let f = (fun y -> x + y) in let x = 10 in f 2 中,
环境与 store 的区别在可变变量处最清楚。若 x := 2 更新的是
类型环境
推论与应用
操作语义可用判断式
实际实现可以把环境做成父指针链、持久映射、栈帧或编译后的词法地址。只要查找、遮蔽和作用域恢复的可观察行为一致,这些表示都实现同一语义角色;环境裁剪还可只保留后续确实会访问的自由变量绑定。
参考资料
- Michael R. Clarkson et al., OCaml Programming: Correct + Efficient + Beautiful, Cornell CS 3110,在线版,2026 年访问,§10.4 Environment Model:闭包、环境扩展与词法作用域。
- Benjamin C. Pierce, Types and Programming Languages, MIT Press, 2002,Chs. 9–11 and 22,evaluation and typing contexts。