为何含call/cc与Break过程的Scheme代码陷入无限循环输出9?
call/cc 实现 Break 导致无限循环的原因解析
问题代码
(define RESUME "ANY THING...") (define BREAK (lambda (msg) (call/cc (lambda (k) (set! RESUME k) ((lambda (x) x) msg))))) (define addition (lambda (x y) (+ x (BREAK 7)))) (define main (lambda args (print (addition 8 5)) (print (RESUME 1))))
运行命令:csi -ss break.scm,程序会持续输出9,陷入无限循环。
原因解析
问题核心在于call/cc 捕获的续延(continuation)包含了后续所有代码的执行逻辑,具体流程拆解如下:
第一次执行流程:
- 进入
main函数,调用(addition 8 5),进入addition后执行(+ 8 (BREAK 7))。 - 调用
BREAK 7时,call/cc会捕获当前的续延k——这个k代表的是「接收一个值v,计算(+ 8 v),将结果传给print输出,然后继续执行main里的下一行(print (RESUME 1))」这整套后续操作。 - 把全局变量
RESUME设为k,然后返回7,于是(+ 8 7)得到15,print输出15,接着执行(print (RESUME 1))。
- 进入
触发循环的关键步骤:
- 调用
(RESUME 1)等价于调用捕获到的续延k,传入参数1。此时程序会跳回call/cc的位置,把(BREAK 7)的返回值替换成1,计算(+ 8 1)得到9,print输出9。 - 续延
k的逻辑还没结束:输出9之后,它会继续执行main函数中(print (addition 8 5))之后的代码——也就是再次调用(print (RESUME 1))。 - 如此反复,每次调用
RESUME都会触发「输出9 → 再次调用RESUME」的循环,导致程序无限输出9。
- 调用
简单说:你以为RESUME只是返回一个值让addition完成计算,但实际上它会带着整个后续代码(包括再次调用自己)一起重复执行,从而形成无限循环。
内容的提问来源于stack exchange,提问作者anru
相关产品推荐
相关产品推荐

