“ ...如何通过将列表作为参数传递给任意大的输入? ”
已发布过程所描述的*factors
过程不是迭代的,即不是尾递归的,它会为大量输入增加堆栈空间。我认为 OP 有兴趣找到该代码的尾递归版本以提高空间效率。
您可以通过将累加器添加到辅助过程来将其转换为迭代过程。这允许将结果存储在累加器中并通过递归调用传递,而不需要在这些调用返回时进行任何进一步的操作,即尾递归。
(define (factors-iter n)
(define (iter d result)
(cond ((> d n) (reverse result))
((zero? (modulo n d))
(iter (+ d 1) (cons d result)))
(else
(iter (+ d 1) result))))
(iter 1 '()))
以下是跟踪这些过程的执行的结果:
> (factors-trace 8)
|(%factors 1 8)
| (%factors 2 8)
| |(%factors 3 8)
| |(%factors 4 8)
| | (%factors 5 8)
| | (%factors 6 8)
| | (%factors 7 8)
| | (%factors 8 8)
| | |(%factors 9 8)
| | |()
| | (8)
| |(4 8)
| (2 4 8)
|(1 2 4 8)
(1 2 4 8)
> (factors-iter-trace 8)
|(iter 1 8 ())
|(iter 2 8 (1))
|(iter 3 8 (2 1))
|(iter 4 8 (2 1))
|(iter 5 8 (4 2 1))
|(iter 6 8 (4 2 1))
|(iter 7 8 (4 2 1))
|(iter 8 8 (4 2 1))
|(iter 9 8 (8 4 2 1))
|(1 2 4 8)
(1 2 4 8)
这里factors-trace
和factors-iter-trace
是factors
和factors-iter
定义的略微修改版本,允许跟踪。您可以看到%factors
进程的堆栈大小随着计算的进行而增长,但iter
堆栈大小保持不变。
正如其他人已经回答的那样,使用factors-iter
输入列表的最简单方法是使用map
:
> (map factors-iter '(4 42 314 2998))
((1 2 4) (1 2 3 6 7 14 21 42) (1 2 157 314) (1 2 1499 2998))