Scheme:带有list append的递归

时间:2013-03-22 03:11:25

标签: recursion scheme

我有一个递归函数,它基本上会以递归方式将元素附加到列表中,直到满足条件为止。但是有一个问题,那就是使用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) '())来运行该功能 我意识到上面的程序是无用的;它只是为了证明我在说什么。

谢谢!

2 个答案:

答案 0 :(得分:1)

您发布的代码的问题不在于该方案会使程序与列表混淆;问题在于调用append

在调试时跟踪过程的执行会很有帮助。以下是我在simpleappend使用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)))))))