简单递归中出现意外错误(Scheme Language)

时间:2016-10-11 03:10:58

标签: recursion scheme racket

我正在使用球拍学习Scheme。我做了以下程序,但它给出了合同违规错误。

预期:(确切非负整数? - >> .any / c) 给出:'()

程序找到一个区间中可被3或5整除的所有数字的列表。

#lang racket

;;Global Definitions
(define upper-bound 10)
(define lower-bound 0)


;;set-bounds: Int, Int -> ()
(define (set-bounds m n)
(set! upper-bound (max m n))
(set! lower-bound (min m n)))

;;get-numbers: () -> (Int)
(define (get-numbers)
    (build-list upper-bound '()))

;;make-list: Int, (Int) -> (Int)
(define (build-list x y)
    (cond
        [(= x lower-bound) y]
        [(= (modulo x 5) 0) (build-list (sub1 x) (cons x y))]
        [(= (modulo x 3) 0) (build-list (sub1 x) (cons x y))]
        [else (build-list (sub1 x) y)]))
编辑:我做了奥斯卡洛佩兹建议的修改。

2 个答案:

答案 0 :(得分:1)

您应首先测试 递归停止的条件 - 即x何时等于lower-bound

(define (build-list x y)
  (cond
    [(= x lower-bound) y]
    [(= (modulo x 5) 0) (build-list (sub1 x) (cons x y))]
    [(= (modulo x 3) 0) (build-list (sub1 x) (cons x y))]
    [else (build-list (sub1 x) y)]))

答案 1 :(得分:1)

另一种方法是使用for/list创建列表:

(define (build-list ub lst)
  (for/list ((i (range lb ub))
             #:when (or (= 0 (modulo i 3))
                        (= 0 (modulo i 5))))
    i))

用法:

(define lb 0)
(build-list 10 '())

输出:

'(0 3 5 6 9)

编辑:

实际上这里不需要:

(define (build-list ub)
  (for/list ((i (range lb ub))
             #:when (or (= 0 (modulo i 3))
                        (= 0 (modulo i 5))))
    i))

所以可以打电话:

(build-list 10)

以下是递归方法的修改(使用'named let'):

(define (build-list2 ub)
  (let loop ((x ub) (lst '()))
    (cond
        [(= x lb) lst]
        [(= (modulo x 5) 0) (loop (sub1 x) (cons x lst))]
        [(= (modulo x 3) 0) (loop (sub1 x) (cons x lst))]
        [else (loop (sub1 x) lst)])))

此外,如果你总是要用空列表'()来调用你的函数,你可以将它作为默认值放在你的参数列表中:

(build-list x (y '()))

然后你可以用简化的命令调用:

(build-list 10)