SBCL中Common Lisp代码执行结果不一致的原因探究
Common Lisp代码跨实现结果不一致的原因
(print (let* ((x nil) (y x)) (setq x t) (and y x))) ; SBCL输出T,其他实现输出NIL (print (let* ((x nil) (y x)) (setq x t) (and x y))) ; 所有实现输出NIL (print (let* ((x nil) (y t)) (setq y x) (setq x t) (and y x))) ; 所有实现输出NIL (defun noop (x) (when x (princ ""))) (print (let* ((x nil) (y x)) (noop y) (setq x t) (and y x))) ; 所有实现输出NIL (print (let* ((x nil) (y x)) (setq x t) (noop y) (and y x))) ; 所有实现输出NIL
这段代码在Linux环境的SBCL 2.4.9中运行时,第一行输出T,其余行均输出NIL;但在CLISP等其他Common Lisp实现中,所有行的输出都是NIL。这种差异看似反常,实际是SBCL的一个优化逻辑bug导致的。
问题根源
根据Common Lisp的语义,let*中y的初始值是绑定时刻x的副本,后续通过setq修改x的值,不应该影响y的取值。但SBCL在编译第一行代码时,错误地将y优化成了对x的直接引用(而非独立变量),导致修改x后,y的值也被同步改变——这就出现了and y x返回T的反常结果。
而其余行的代码因为存在额外操作(比如and的顺序调换、调用noop函数),干扰了SBCL的优化逻辑,使其没有触发这个bug,所以结果符合预期。
后续进展
- 更新1:已将该问题提交至SBCL的bug追踪系统
- 更新2:SBCL项目维护者很快针对该问题提交了修复代码
内容的提问来源于stack exchange,提问作者single-question-123
相关产品推荐
相关产品推荐

