Recursion 简单递归中出现意外错误(Scheme语言)

Recursion 简单递归中出现意外错误(Scheme语言),recursion,scheme,racket,Recursion,Scheme,Racket,我正在用球拍学习这个计划。我做了以下程序,但它给出了一个违反合同的错误 应为:(精确非负整数?->.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 (

我正在用球拍学习这个计划。我做了以下程序,但它给出了一个违反合同的错误

应为:(精确非负整数?->.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)]))
编辑:我做了Oscar Lopez建议的更改。

您应该首先测试递归停止的条件,即当
x
等于
下限时:

(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)]))
您应该首先测试递归停止的条件,即当
x
等于
下限时:

(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)]))

另一种方法是使用
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)
编辑:

实际上,这里不需要lst:

(define (build-list ub)
  (for/list ((i (range lb ub))
             #:when (or (= 0 (modulo i 3))
                        (= 0 (modulo i 5))))
    i))
因此,我们可以称之为:

(build-list 10)
以下是对递归方法的修改(使用“命名let”):

此外,如果您总是必须使用空列表“()”调用函数,则可以将其作为默认值放在参数列表中:

(build-list x (y '()))
然后,您可以使用简化的命令调用:

(build-list 10)

另一种方法是使用
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)
编辑:

实际上,这里不需要lst:

(define (build-list ub)
  (for/list ((i (range lb ub))
             #:when (or (= 0 (modulo i 3))
                        (= 0 (modulo i 5))))
    i))
因此,我们可以称之为:

(build-list 10)
以下是对递归方法的修改(使用“命名let”):

此外,如果您总是必须使用空列表“()”调用函数,则可以将其作为默认值放在参数列表中:

(build-list x (y '()))
然后,您可以使用简化的命令调用:

(build-list 10)


一个小笑话:一个空列表应该被定义为
'()
,而不是
`()
(也就是说:使用一个引号,而不是一个反勾号,这意味着不同的东西。)不,如图所示的程序完全没有任何作用。@WillNess我知道。我使用REPL运行它。“对不起,我忘了提它了。”斯卡洛佩斯早些时候我用空的。它仍然不起作用。这两者有什么区别?我的意思是,在REPL中,它就像“()should.Empty”和“()”是一个相同的小笑话:空列表应该定义为
”()
,而不是
`()
(也就是说:使用一个引号,而不是一个反勾,这意味着不同的东西。)不,如图所示的程序完全没有任何功能。@Willence我知道。我使用REPL运行它。“对不起,我忘了提它了。”斯卡洛佩斯早些时候我用空的。它仍然不起作用。这两者有什么区别?我的意思是,在REPL中,它就像“()should.Empty”和“()”是sameI想要尝试的方法,看看如何以这种方式做事情。但无论如何,谢谢,我也会尝试这个版本。谢谢递归解决方案。我只是想尝试一下这种方法,看看如何用这种方式做事情。但无论如何,谢谢,我也会尝试这个版本。谢谢递归解决方案。正如你所说,我把下限条件移到了顶部。但它还是给了我同样的错误。我理解将其放在顶部的原因。我认为问题在于为
构建列表
声明的类型,您使用的是类型化的racket吗?它应该是
makelist:Int,Int->(Int)
我只是使用“开箱即用”的球拍安装。所以,我猜它不是打字的球拍。我只是添加了类型,因为我在一些网站上读到这是一个很好的实践。然后尝试删除它们:P因为开箱即用,上面的代码适用于meI,正如您所说,将下限条件移到了顶部。但它还是给了我同样的错误。我理解将其放在顶部的原因。我认为问题在于为
构建列表
声明的类型,您使用的是类型化的racket吗?它应该是
makelist:Int,Int->(Int)
我只是使用“开箱即用”的球拍安装。所以,我猜它不是打字的球拍。我只是添加了这些类型,因为我在一些网站上读到这是一个很好的做法。然后尝试删除它们:P因为开箱即用,上面的代码对我很有用