球拍什么时候会在函数中检查结构的类型?

When racket will check the struct's type in a function?

这个节目:

(struct pt (x y))

(define (distance p1 p2)
(sqrt (+ (sqr (- (pt-x p2) (pt-x p1)))
       (sqr (- (pt-y p2) (pt-y p1))))))

(distance (pt 0 0) (pt 3.1415 2.7172))

工作正常。如果加一行:

(struct pt2 (x y))

然后

(distance (pt 0 0) (pt2 3.1415 2.7172))

遇到错误

pt-x: contract violation
expected: pt?
given: #<pt2>

我认为是因为函数 distance 使用“pt-x”和“pt-y”来检查结构的类型。在其他静态类型语言中,类型声明和类型检查会发生在函数的头部,像这样:

(define (distance p1:pt p2:pt)

所以作为球拍,如果在“(定义(距离p1 p2)”之后可能有100行代码,并且需要1分钟,然后行“(sqrt(+(sqr(-(pt -x p2) (pt-x p1)))", 发现类型错误,所以会浪费1分钟?

谢谢!

我不确定你所说的“浪费 1 分钟”是什么意思。

  • 从某种意义上说,在调用distance之后,(pt-x p2)可能需要1分钟才能执行?
  • 或者从某种意义上说,整个程序可能需要 1 分钟才能执行 (pt-x p2)

如果你指的是第一个,你可以在distance中添加一个合同。例如,

#lang racket

(struct pt (x y))

(define/contract (distance p1 p2) (-> pt? pt? number?)
  (sqrt (+ (sqr (- (pt-x p2) (pt-x p1)))
           (sqr (- (pt-y p2) (pt-y p1))))))

(distance (pt 0 0) (pt 3.1415 2.7172))

每次调用distance时,都会检查p1p2是否满足pt?,如果检查失败,则立即报错。请注意,这发生在 运行 时间并且仅在调用 distance 时发生。程序可能运行长时间没有问题,然后执行(distance (pt2 0 0) (pt2 3.1415 2.7172)),才会出现错误。


如果你指的是第二个,那么你根本不希望程序是 运行 以便发现错误。也就是说,您希望静态地发现错误。你需要使用 Typed Racket 或类似的东西。这类似于具有静态类型检查的语言。

#lang typed/racket

(struct pt ([x : Number] [y : Number]))

(: distance : pt pt -> Number)
(define (distance p1 p2) 
  (sqrt (+ (sqr (- (pt-x p2) (pt-x p1)))
           (sqr (- (pt-y p2) (pt-y p1))))))

(distance (pt 0 0) (pt 3.1415 2.7172))