(define (square-list items)
(define (iter things answer)
(if (null? things)
answer
(iter (cdr things)
(cons (square (car things))
answer))))
(iter items nil))
当我进入
(square-list (list 1 2 3 4))
它返回(16 9 4 1) - 为什么这会倒退?
答案 0 :(得分:4)
您正在使用尾递归构建输出列表,为此,您将通过附加到列表的 head 来累积answer
。当然,这将产生相反的列表。你有两个解决这个问题的方法,一个是放弃尾递归:
(define (square-list items)
(if (null? items)
nil
(cons (square (car items))
(square-list (cdr items)))))
其他,在处理之前撤消列表:
(define (square-list items)
(define (iter things answer)
(if (null? things)
answer
(iter (cdr things)
(cons (square (car things))
answer))))
(iter (reverse items) nil))
还有另一种选择:在最后添加元素,而不是将它们包括在内:
(define (square-list items)
(define (iter things answer)
(if (null? things)
answer
(iter (cdr things)
(append answer
(list (square (car things)))))))
(iter items nil))
每个选项都有自己的权衡,但是:
考虑到所有事情,最好的尾递归选项将是第二个。
答案 1 :(得分:1)
问题在于您的cons
声明。如果您从以下地址切换订单:
(cons (square (car things)) answer)
致:
<击> (cons answer (square (car things)))
击>
您的列表将按照您想要的顺序出现。
我总觉得这样写起来容易得多:
(define (square-list2 items)
(square-list-helper items '())
)
(define (square-list-helper items squares)
(cond
[(empty? items) squares]
[else (append
squares
(square-list-helper (cdr items) (list (square (car items)))))]
)
)
答案 2 :(得分:1)
看看两个元素的简单情况:
(square-list '(2 3))
这导致:
(iter '(3)
(cons (square 2) nil))
==
(iter '(3) '(4))
然后递归调用:
(iter '()
(cons (square 3) '(4))
==
(iter '() '(9 4))
然后,这会调用iter
的基本情况,只返回answer
。
所以它正在向前遍历列表,但是在处理每个元素时,正方形被放在answer
列表的 front 上,因此结果是向后构建的。
简单的解决方法是将(cons (square (car things)) answer)
更改为:
(append answer (list (square (car things))))
这会将新结果放在最后而不是开头。但是,这通常被认为是一种不好的方法,因为它必须每次重建结果列表,复制O(n)元素。
答案 3 :(得分:0)
您的输入顺序错误:首先是递归处理的列表的其余部分,然后是处理当前元素的结果。这将在处理它的同时反转您的列表。试试这个:
(define (square-list items)
(define (iter things answer)
(if (null? things)
answer
(iter (cdr things)
(append answer (list (square (car things)))))))
(iter items (list)))