【问题标题】:scheme contract violation error计划合同违约错误
【发布时间】:2016-10-20 00:56:06
【问题描述】:
(define (real x) (car x))
(define (imag x) (cdr x))
(define (complex-sqrt x)
    (define (first a b) (sqrt (/ (+ a
                              (sqrt (+
                                     (* a a)
                                     (* b b))))
                           2)))
    (define (second a b) (sqrt (/ (+ (* -1 a)
                               (sqrt (+
                                      (* a a)
                                      (* b b))))
                            2)))
(cons (first (real x) (imag x)) (second (real x) (real y))))
(complex-sqrt '(2 3))

当它尝试评估(第一个 a b)和(第二个 a b)时,我不断收到一条错误消息,上面写着“* 违反合同:预期数字”。我不确定此信息是否相关,但输入将始终是 2 个数字的列表。

【问题讨论】:

  • 您使用的是#lang racket 还是其中一种学生语言?
  • 我使用的是 R5RS 语言。
  • (2 3) 等于 (cons 2 (cons 3 null))。我认为您的意思是使用 (cons 2 3) 作为输入。
  • 在您当前的代码中,'y' 未绑定。我认为'real y'应该是'imag x'

标签: compiler-errors scheme racket


【解决方案1】:

您没有包含完整的示例,因此很难说出了什么问题。 也许您调用 complex-sqrt 时使用了错误类型的参数?

这对我有用:

#lang r5rs
(define (real x) (car x))
(define (imag x) (cdr x))
(define (complex-sqrt x)
  (define (first a b) (sqrt (/ (+ a
                                  (sqrt (+
                                         (* a a)
                                         (* b b))))
                               2)))
  (define (second a b) (sqrt (/ (+ (* -1 a)
                                   (sqrt (+
                                          (* a a)
                                          (* b b))))
                                2)))
  (cons (first  (real x) (imag x))
        (second (real x) (imag x))))

(display (complex-sqrt (cons 1 2)))
(newline)

【讨论】:

  • 从问题的最后一句话来看,看起来 OP 试图传递 (list 1 2) 而不是一对。
  • 听起来很可能。你还记得这是否是 SICP 练习吗?
  • @sara 那你需要把imag的定义改成(define (imag x) (car (cdr x)))
【解决方案2】:

变化:

(define (imag x) (cdr x))

到:

(define (imag x) (second x))

(这是内置的“第二”功能,而不是您的第二功能。它相当于(car (cdr lst))或列表的第二项)。

然后它起作用了:

(complex-sqrt '(2 3))
; output:  '(1.6741492280355401 . 0.895977476129838)

(cdr x) 是一个列表,而(second x) 是一个项目。

完整的原始错误清楚地提到了这一点:

*: contract violation
  expected: number?
  given: '(3)                     ; <<<<<< NOTE
  argument position: 1st
  other arguments...:

“*”功能需要项目而不是列表。

此外,您不应使用“first”和“second”作为您自己的函数名称,因为它们是内置函数(用于获取任何列表的第一个和第二个元素)。见here

函数中的倒数第二个语句:

(cons (first (real x) (imag x)) (second (real x) (real y))))

应该缩进,因为它是 complex-sqrt 函数的一部分。 (提示:要轻松对 DrRacket 中的整个代码应用适当的缩进,请全选并按 Tab。)

(real y) 应该是(imag x)

【讨论】:

  • 词汇范围内的阴影是可以的,但有风险。只有当它的功能仍然与报表相同时,才可以在报表中重新定义全局变量。因此 OPs second 在全局命名空间中是不行的,因为它不支持对。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多