2013-11-24 55 views
1

我在追隨球拍領域。下面的代碼引發以下錯誤:找不到合同違規和球拍結構錯誤

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)條件調試affirmates,座標是不是一個座標。定義當前的狀態爲座標如下大爆炸功能之前還沒有解決的錯誤:

(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 

什麼可能是在這裏的錯誤的原因是什麼?

編輯

@格雷格Hendershott:設置座標-ALT!是in the struct document of racket爲:

set-id-field-id !,對於每個包含#:可變選項的字段,或者當#:可變選項被指定爲結構選項時;一個帶有結構類型實例和一個新字段值的增變程序。該結構被破壞性地用新值更新,並返回#<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指出,應該建立一個新的結構,我更新了結構如下:

​​

之後,停止UFO成了簡單:

(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分支的級聯中是否是勢在必行的風格。

+0

這確實有效,但它不是在球拍和功能語言中做事情的首選方式。除了「修改」一個現有的pos,你應該在結構定義中刪除'#:mutable'關鍵字,而在你的'increment'函數中你應該創建一個新的pos(這實際上比變換一個簡單, 這裏)。 – Metaxal

+0

哦,我明白了,這就是「破壞性」意味着什麼。我喜歡功能性的方法,並試圖學習系統性,但我很難弄清楚這種變化。謝謝你的提示。 – barerd

+0

@Metaxal:我試圖用struct-copy和一些begin語句創建一個新的pos,但是不能成功。你能非常介意地引導我一個關於它的文件嗎? – barerd

回答

0

當函數應該返回一個值但通常不會返回值時,通常會出現類似given: #<void>的錯誤。例如,壞:

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

與好:

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

它看起來像big-bang中的on-tick子句的所有變體應該返回HandlerResult而不是#<void>

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

什麼是set-coord-alt!它有什麼回報?

+0

非常感謝您對延遲表示歉意,我深入瞭解了這些文檔。請參閱編輯。總之,當我在增量函數的末尾添加了一個'pos'時,它就起作用了。 – barerd