计算包含从x到y的数字的列表

时间:2013-03-19 06:08:41

标签: scheme racket

如何创建一个方法,该方法需要两个数字并从第一个数字到第二个数字准备一个列表。第一个数字总是正数而不是第二个数字?我尝试了以下但我不知道如何在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)

有人可以帮忙解决这个问题吗?

2 个答案:

答案 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过程基本相同。