将列表的"后端"用于任何事情是非常罕见的,它既低效又容易导致相当复杂的代码(正如您所注意到的那样).
为了反转列表,您可以保存第一个元素,反转其余元素,然后将旧的第一个元素放在"反向休息"的后面.
(这与您正在进行的操作相同,但在列表的另一端.)
那是,
(define (reverse lst) (if (null? lst) lst (append (reverse (cdr lst)) (list (car lst)))))
这是非常低效的,所以通常你会使用尾递归版本(SICP中的"迭代过程").
如果将它分解为主函数和"帮助器",则可能最容易理解尾递归实现:
(define (reverse-helper lst acc) (if (null? lst) acc (reverse-helper (cdr lst) (cons (car lst) acc)))) (define (reverse lst) (reverse-helper lst '()))
主要区别在于在acc
参数中构建结果意味着我们可以使用cons
而不需要重复遍历结果以在其后面添加内容(这就是做什么append
).
将列表的"后端"用于任何事情是非常罕见的,它既低效又容易导致相当复杂的代码(正如您所注意到的那样).
为了反转列表,您可以保存第一个元素,反转其余元素,然后将旧的第一个元素放在"反向休息"的后面.
(这与您正在进行的操作相同,但在列表的另一端.)
那是,
(define (reverse lst) (if (null? lst) lst (append (reverse (cdr lst)) (list (car lst)))))
这是非常低效的,所以通常你会使用尾递归版本(SICP中的"迭代过程").
如果将它分解为主函数和"帮助器",则可能最容易理解尾递归实现:
(define (reverse-helper lst acc) (if (null? lst) acc (reverse-helper (cdr lst) (cons (car lst) acc)))) (define (reverse lst) (reverse-helper lst '()))
主要区别在于在acc
参数中构建结果意味着我们可以使用cons
而不需要重复遍历结果以在其后面添加内容(这就是做什么append
).