方案R5RS合同违规

时间:2018-03-31 05:29:02

标签: scheme r5rs

以下代码是教授在我的计划课程简介中给出的答案,但它出现了错误。看不出原因。

#!r5rs

(define (make-complex a b) (cons a b))
(define (real x) (car x))
(define (imag x) (cdr x))

(define (complex-sqrt x)
  (define (sgn v)
    (cond ((< v 0) -1)
          ((= v 0) 0)
          (else 1)))
  (let ((root (sqrt (+ (* (real x) (real x))
                       (* (imag x) (imag x))))))
    (make-complex (sqrt (/ (+ (real x) root) 2))
                  (*  (sgn (imag x))
                      (sqrt (/ (- root (real x)) 2))))))

(complex-sqrt 7)
;; ERROR mcar: contract violation
;; expected: mpair? 
;; given: 7

在DrRacket中运行时,我使用trace illustartion获取了screenshot错误。

2 个答案:

答案 0 :(得分:0)

此处您的代码已转录。请考虑将来发布实际代码而不是屏幕截图。

(define (make-complex a b) (cons a b))
(define (real x) (car x))
(define (imag x) (cdr x))

(define (complex-sqrt x)
    (define (sgn v)
        (cond ((< v 0) -1)
              ((= v 0) 0)
              (else 1)))
    (let ((root (sqrt (+ (* (real x) (real x))
                         (* (imag x) (imag x))))))
         (make-complex (sqrt (/ (+ (real x) root) 2))
                       (*  (sgn (imag x))
                           (sqrt (/ (- root (real x)) 2))))))

你的教授也提供了(complex-sqrt 7)部分吗?我们试图得到一个复数的平方根,所以我们应该传递一个复数:

(complex-sqrt (make-complex 5 2))
'(2.27872385417085 . 0.43884211690225433)

根据https://www.wolframalpha.com/input/?i=sqrt(2i%2B5)的说法是正确的!

答案 1 :(得分:0)

complex-sqrt的实施是不安全的。这意味着它假设你传递一个复数,在这种情况下是用make-complex创建的。

要解决此问题,您需要检查参数是否复杂:

;; Not 100%. Should use `struct` to not
;; mix with random pairs that happens to have numeric parts
(define (complex? x)
  (and (pair? x)
       (number? (car x))
       (number? (cdr x))))


;; The original code is renamed to unsafe-complex-sqrt
(define (complex-sqrt x)
  (if (complex? x)
      (unsafe-complex-sqrt x)      
      (raise-argument-error 'complex-sqrt "complex?" x)))

现在你可以测试一下:

(complex-sqrt (make-complex 7 0)) 
; ==> (2.6457513110645907 . 0)

(complex-sqrt 7)
; ERROR complex-sqrt: contract violation
; expected: complex?
; given: 7

完美。现在它说你有mot将所需的复数传递给一个需要复杂数字才能工作的函数。

那么原始代码中发生了什么? 在unsafe-complex-sqrt carcdr使用x#t这些安全操作,如果(pair? x)提供的参数mcons不是#!r5rs,则表示违反合同。

Racket在其<input mdInput placeholder="Name" #filterName name="filterName" > @ViewChild() input: ElementRef public clear() { this.input.NativeElement.value = ''; } 实现中使用markAsPristine(),因此错误是指R5RS中以m为前缀的每对/列表函数,因为错误没有注意重命名。