无法弄清球拍中的合同违规和结构错误

时间:2013-11-24 14:00:14

标签: racket

我正在追随球拍的境界。下面的代码抛出以下错误:

coord-lat: contract violation
expected: coord?
given: #<void>

飞ufo.rkt

#lang racket

(require 2htdp/universe 2htdp/image)
(struct coord (alt lat) #:transparent #:mutable)

(define WIDTH 400)
(define HEIGHT 400)
(define UFO *some_picture*)

(define (move-ufo pos)
  (place-image/align UFO
                     (coord-alt pos)
                     (coord-lat pos)
                     "left" "top"
                     (empty-scene WIDTH HEIGHT)))

(define (increment pos)
  (set-coord-alt! pos (+ 2 (coord-alt pos)))
  (set-coord-lat! pos (+ 1 (coord-lat pos))))

 (define (at-the-border pos)
  (>= (coord-lat pos) (- HEIGHT 20)))

(big-bang (coord 0 0)
          (on-tick increment)
          (to-draw move-ufo)
          (stop-when at-the-border))

为调试添加(coord? pos)条件,确认坐标不是坐标。在下面的大爆炸函数之前将当前状态定义为坐标也不能解决错误:

(define s (coord 0 0))

(big-bang s...

我检查了球拍contractstruct文件,但找不到原因。由于使用了define-struct的许多示例,我也尝试了make-coord,但这也无济于事。球拍文件还建议struct is preferred

向协调员添加合约

(provide coord)
(define-struct/contract coord ([alt number?]
                               [lat number?])
  #:transparent
  #:mutable)

导致以下错误:

    coord-lat: contract violation
 expected: coord?
 given: #<void>
 in: the 1st argument of
      (-> coord? number?)
 contract from: (struct coord)
 blaming: fly-ufo.rkt
 at: fly-ufo.rkt

这里可能是错误的原因是什么?

修改

@Greg Hendershott:set-coord-alt!是in the struct document of racket为:

set-id-field-id!,用于包含#:mutable选项的每个字段,或者当#:mutable选项指定为struct-option时;一个mutator过程,它接受结构类型的实例和新的字段值。使用新值破坏性地更新结构,并返回#<void>

所以,当我读完最后一句话时,我得到了函数返回#<void>的原因,我之前错过了它。因此,为了返回坐标而不是#<void>,我在增量函数的末尾添加了pos

(define (increment pos)
  (set-coord-alt! pos (+ 2 (coord-alt pos)))
  (set-coord-lat! pos (+ 1 (coord-lat pos)))
  pos)

并且有效。

第二次编辑

我把这个只是为了将来的参考。在Metaxal注意到应该创建一个新结构之后,我更新了结构如下:

;; a struct for the current state, where:
;; field 1 is x coordinate
;; field 2 is y coordinate
;; field 3 is horizontal speed
;; field 4 is vertical speed
(struct cs (lat alt hspeed vspeed))

此后,停止不明飞行物变得如此简单:

(define (stop ufo)
  (cs (cs-lat ufo) (cs-alt ufo) 0 0))

并且加速成为:

(define (up-wards ufo)
  (cond [(> (cs-vspeed ufo) (- MAX-SPEED))
         (struct-copy cs ufo [vspeed (sub1 (cs-vspeed ufo))])]
        [#t (play-sound some-sound-file #t)
            ufo]))

现在我唯一想知道的是,将play-sound-fileufo置于else分支的级联中是否是必要的风格。

1 个答案:

答案 0 :(得分:0)

一般来说,当一个函数应该返回一个值时,你会得到像given: #<void>这样的错误,但是没有。例如,坏:

(define (increment x)
  (set! x (add1 x)))
;; set! returns void, therefore increment returns void

VS。好:

(define (increment x)
  (add1 x))
;; returns a number

虽然我不熟悉大爆炸,但看起来你有类似的问题:

(define (increment pos)
  (set-coord-alt! pos (+ 2 (coord-alt pos)))
  (set-coord-lat! pos (+ 1 (coord-lat pos))))

  . . . .

(big-bang (coord 0 0)
          (on-tick increment)
          (to-draw move-ufo)
          (stop-when at-the-border))

看起来on-tickbig-bang子句的所有变体都应该返回HandlerResult,而不是#<void>

来源:http://docs.racket-lang.org/teachpack/2htdpuniverse.html#(form._world._((lib._2htdp/universe..rkt)._to-draw))

什么是set-coord-alt!以及它返回了什么?