1

我有一个递归函数,它基本上保持递归地将元素附加到列表中,直到满足条件。但是有一个问题,那就是使用append,我们必须给它一个引用列表。这样做

 (append (1 2) 3)

给我们一个错误。

问题是当我第一次将一个列表传递给参数时,我可以把'它变成一个带引号的列表。但是,一旦我将某些内容附加到该列表并且它再次递归地传递给同一个函数,第二次append尝试工作,它将看到不再引用该列表,因此Scheme认为它是一个过程而不是一个列表。让我向您展示代码的简化版本:

 (define simple
   (lambda (x y)
      (if (equal? x '()) 
          (display 'success!)
          (simple (cdr x) (append y (car x))))))

我们通过do来运行函数(simple '(1 2 3) '()) 我意识到上面的程序是没用的;这只是为了证明我在说什么。

谢谢!

4

2 回答 2

1

您发布的代码的问题不在于 Scheme 将过程与列表混淆了;问题在于调用append.

在调试时跟踪过程的执行会很有帮助。以下是我在 Petite Chez Scheme 中使用为simpleand开启跟踪的情况下运行您的代码时显示的内容:appendtrace-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>
于 2013-03-22T04:02:05.353 回答
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)))))))
于 2013-03-22T03:51:06.937 回答