如何创建一个方法,该方法需要两个数字并从第一个数字到第二个数字准备一个列表。第一个数字总是正数而不是第二个数字?我尝试了以下但我不知道如何在Scheme中有一个全局变量来保存以前的值。
(define preplist
(let ((temp '()))
(lambda (x y)
(cond ((= x y) (append temp (list x)))
(else (append temp (list x))
(display x)
(preplist (+ x 1) y))))))
预期结果是:( preplist 3 7)=> (3 4 5 6 7)
有人可以帮忙解决这个问题吗?
答案 0 :(得分:1)
(x,y)的解可以计算为:将x放在(x + 1,y)的前面。因此它显然是递归的。像这样:
(define (preplist x y)
(if (= x y)
(list y)
(cons x (preplist (+ x 1) y))))
看,它有效:
> (preplist 1 4)
(1 2 3 4)
> (preplist 5 7)
(5 6 7)
答案 1 :(得分:1)
您的代码中存在多个错误,对于初学者而言,您不需要在let
中定义用于存储结果的全局变量,这足以在递归中建立答案。在这种情况下不要使用append
,如果密切关注解决方案模板,cons
就足以构建输出列表。
您应该坚持使用递归建立新列表的方法;这就是使用该配方解决问题的方法,它可能更像是这样的惯用语:
(define preplist
(lambda (x y)
(cond ((> x y) ; if the exit condition is met
empty) ; then return the empty list
(else ; otherwise
(cons x ; cons the current element
(preplist (add1 x) y)))))) ; and advance the recursion
完全不同的方法是编写尾递归解决方案。这更有效,因为使用了恒定量的堆栈。它不遵循上面概述的设计方法,但有点类似于您想到的解决方案 - 但请记住,这不使用全局变量(只有一个名为let
的迭代)并且解决方案被累积并作为参数传递:
(define (preplist x y)
(let loop ((i y) ; named let for iteration
(acc empty)) ; define and initialize parameters
(if (> x i) ; if exit condition is met
acc ; return accumulated value
(loop (sub1 i) ; otherwise advance recursion
(cons i acc))))) ; and add to the accumulator
当然,正如@dyoo在评论中指出的那样,在实际设置中,您将使用内置的range
过程,该过程与preplist
过程基本相同。