为何在Guile中定义recursive-display过程会引发无限循环?
为什么这段Guile代码会引发无限循环?
先看问题代码:
(define (recursive-display . args) (if (null? args) #t (begin (display (car args)) (recursive-display (cdr args)))))
核心原因:可变参数的打包逻辑
recursive-display用. args定义了可变参数,这意味着所有传入的参数会被自动打包成一个列表绑定到args上。问题就出在递归调用的写法上:
当你写(recursive-display (cdr args))时,(cdr args)本身会被当作单个参数传入,新的args会变成((cdr args))(一个包含子列表的单元素列表),而不是直接把(cdr args)的元素作为参数展开。
举个具体执行流程的例子,假设初始调用是(recursive-display 1 2):
- 第一次调用:
args = (1 2),显示1,然后调用(recursive-display (2)) - 第二次调用:
args = ((2)),显示(2),然后调用(recursive-display (cdr args))——此时(cdr args)是(),所以调用变成(recursive-display ()) - 第三次调用:
args = (())(因为传入的()是单个参数,被打包成列表),不满足(null? args)的终止条件,显示()后再次调用(recursive-display (cdr args)),也就是(recursive-display ()),从此进入无限循环。
解决方法
用apply函数把(cdr args)的元素展开作为参数传入,修改递归调用行:
(apply recursive-display (cdr args))
apply会把第二个参数(列表)里的元素逐个传递给第一个参数指定的函数,这样新的args就会是(cdr args)本身,而不是包含它的单元素列表,就能正常触发终止条件。
内容的提问来源于stack exchange,提问作者Amanda Ferrari
相关产品推荐
相关产品推荐

