我有一个递归函数,它基本上会以递归方式将元素附加到列表中,直到满足条件为止。但是有一个问题,那就是使用append
,我们必须给它一个引用列表。这样做
(append (1 2) 3)
给了我们一个错误。
问题是当我第一次将列表传递给参数时,我可以将'
设为引号列表。但是,一旦我将某些内容添加到该列表并再次以递归方式传递给同一函数,第二次append
尝试工作,它将看到列表不再被引用,因此Scheme认为它是一个过程而不是一个列表。让我向您展示代码的简化版本:
(define simple
(lambda (x y)
(if (equal? x '())
(display 'success!)
(simple (cdr x) (append y (car x))))))
我们通过执行(simple '(1 2 3) '())
来运行该功能
我意识到上面的程序是无用的;它只是为了证明我在说什么。
谢谢!
答案 0 :(得分:1)
您发布的代码的问题不在于该方案会使程序与列表混淆;问题在于调用append
。
在调试时跟踪过程的执行会很有帮助。以下是我在simple
和append
使用trace-define
开启跟踪时运行代码时所显示的内容:
> (simple '(1 2 3) '())
|(simple (1 2 3) ())
| (append () 1)
| 1
|(simple (2 3) 1)
| (append 1 2)
因为(append () 1)
返回1
,所以在对simple
的第一次递归调用中,第二个参数是1
而不是列表。因此,下次调用append
时会出现错误。
您可以通过将(car x)
来电包裹在list
的来电中来解决此问题:
(define simple
(lambda (x y)
(if (equal? x '())
(display 'success!)
(simple (cdr x) (append y (list (car x)))))))
这里有一个正在运行的固定版本的痕迹:
> (simple '(1 2 3) '())
|(simple (1 2 3) ())
| (append () (1))
| (1)
|(simple (2 3) (1))
| (append (1) (2))
| (1 2)
|(simple (3) (1 2))
| (append (1 2) (3))
| (1 2 3)
|(simple () (1 2 3))
success!|#<void>
答案 1 :(得分:0)
要将元素附加到列表末尾,请将元素放在列表中(append
在列表之间仅定义 )。例如,在您的代码中执行以下操作:
(append y (list (car x)))
当然,这并没有改变程序无所事事的事实。至少,返回y
中累积的值:
(define simple
(lambda (x y)
(if (equal? x '())
y
(simple (cdr x)
(append y (list (car x)))))))