代码之家  ›  专栏  ›  技术社区  ›  Avrohom Yisroel

为什么球拍将#<void>传递给我的函数而不是状态?

  •  0
  • Avrohom Yisroel  · 技术社区  · 4 年前

    我正在学习Racket,并使用《Racket的领域》一书。我已经到了这样的地步,他们向你展示了如何为图像在窗口中向下移动设置动画,然后建议你尝试修改它,以对向左或向右箭头键的按下做出反应,从而将图像侧向移动。

    看起来很简单。。。

    #lang racket
    
    (require 2htdp/universe 2htdp/image)
    
    (define WIDTH 500)
    (define DX 0)
    (define HEIGHT 500)
    (define IMAGE .) ; The image doesn't show up here
    
    (define (add3-to-state current-state)
      (+ current-state 3))
    
    (define (draw-image current-state)
      (place-image IMAGE (+ DX (/ WIDTH 2)) current-state (empty-scene WIDTH HEIGHT)))
    
    (define (state-is-500 current-state)
      (>= current-state 459))
    
    (define (set-delta current-state key)
      (set! DX (+ DX 10)))
    
    (big-bang 0
      (on-tick add3-to-state)
      (on-key set-delta)
      (to-draw draw-image)
      (stop-when state-is-500)
      )
    

    当我运行此程序时,图像会像以前一样向下移动,但一旦我按下某个键,就会出现错误。。。

    >=: contract violation
       expected: real?
       given: #<void>
    

    …在 state-is-500 功能。

    有人能解释为什么会发生这种情况吗?据我所知,我的功能 on-key 与书中展示的形式相同。

    我试着修改 状态is-500 函数看起来像这样。。。

    (define (state-is-500 current-state)
      (printf "~a\n" current-state)
      (>= current-state 459))
    

    …我得到的输出是。。。

    102
    105
    #<void>
    

    …在错误发生之前。

    所以看起来像 #<void> 正在传递给函数,但为什么?

    谢谢

    0 回复  |  直到 4 年前
        1
  •  2
  •   mmmmmm    4 年前

    问题是,bigbang期望key上的函数调用返回游戏的新状态。您不会返回任何内容,因此框架会报告 <void>

    因此,如果状态没有改变,您应该只返回输入状态,例如。

    (define (set-delta current-state key)
      current-state)
    

    此外,这个框架和Racket本身让你不想改变变量,也就是说,你不给它们赋值,或者至少只给它们赋值一次。因此 set! 这不是你应该经常使用的东西。

    在这种情况下,书籍提供的应用程序的状态只是垂直距离,所以只是一个数字,如所示 add3-to-state 原始状态作为第一个参数传递给大爆炸。

    你必须做出的改变是,当前的状态不仅是上下运动,而且是左右运动。此移动显示为第二个参数 place-image 因此,你必须有一个状态来提供第二和第三个参数。