我正在使用球拍学习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)]))
编辑:我做了奥斯卡洛佩兹建议的修改。
答案 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)