如何将图形对象列表映射到符号集合?使用`(define-values)`?

时间:2019-06-26 09:02:46

标签: racket

我正在尝试通过遵循“球拍领域”中的代码示例来学习球拍。目前在第8章,我决定重构一些重复的代码以帮助自己更快地学习。具体来说,我正在尝试将游戏图形列表分配给一组符号,但是我总是遇到错误。

这是原始的orc-world.rkt源文件。该代码可以正常工作。

(require 2htdp/image)

;; compute constants for image frames 
(define ORC     (bitmap "graphics/orc.png"))
(define HYDRA   (bitmap "graphics/hydra.png"))
(define SLIME   (bitmap "graphics/slime.bmp"))
(define BRIGAND (bitmap "graphics/brigand.bmp"))

(define PIC-LIST (list ORC HYDRA SLIME BRIGAND))
(define w (apply max (map image-width PIC-LIST)))
(define h (apply max (map image-height PIC-LIST)))

(define PLAYER-IMAGE  (bitmap "graphics/player.bmp"))

(define FRAME (rectangle w h 'outline 'white))
(define TARGET (circle (- (/ w 2) 2) 'outline 'blue))

(define ORC-IMAGE     (overlay ORC FRAME))
(define HYDRA-IMAGE   (overlay HYDRA FRAME))
(define SLIME-IMAGE   (overlay SLIME FRAME))
(define BRIGAND-IMAGE (overlay BRIGAND FRAME))

基本上,它是从磁盘读取一堆位图图像并将其分配给符号。有很多代码重复。我正在尝试更改它,以使代码重复最小化,同时更多地了解Racket的标准库如何工作。

我的版本,暂时忽略(overlay)代码:

(require 2htdp/image)

(define BASEPATH "/Applications/Racket v7.3/share/pkgs/realm/chapter8/graphics/")
(define FILENAMES '("orc.png" "hydra.png" "slime.bmp" "brigand.bmp" "player.bmp"))
(define PATHS (map (lambda (x)(string-append BASEPATH x)) FILENAMES))
(define PICTURES (map (lambda (x)(bitmap/file x)) PATHS))
(define PIC-LIST '(ORC HYDRA SLIME BRIGAND PLAYER-IMAGE))

我希望遍历图片列表,并将每张图片分配给列表中的符号。我可以做一个(define ORC (first PICTURES)) (define HYDRA (second PICTURES))等但这不是想要的。似乎我们可以使用(map),因为两者都是相同长度的列表,但是出现以下错误。

(map (lambda x y)(define x y) PIC-LIST PICTURES) ; error. define: not allowed in an expression context in: define

(map (lambda x y (define-values (x) (values y)) PIC-LIST PICTURES)) ; error. define-values: not allowed in an expression position in: (define-values (x) (values y))

(map (lambda (x y)(define x y))PIC-LIST PICTURES) ; error. begin (possibly implicit): no expression after a sequence of internal definitions in:
;  (begin (define x y))
;  (define x y)

单独使用(define-values)也不起作用。

(define-values PIC-LIST (values PICTURES)) ; syntax error because PIC-LIST is a list

希望有人会友善地指出我正确的道路。我忽略了这件事一定很简单,因为这是一项非常常见的任务。

感谢您阅读本文。

1 个答案:

答案 0 :(得分:1)

您可以像这样使用match-define

 (match-define (list ORC HYDRA SLIME BRIGAND PLAYER-IMAGE) IMAGES)

只要事先知道图像数量,它就可以工作,您不能将变量名列表作为参数传递(我们在这里进行 pattern matching 。)

我想这没关系-因为无论如何,您应该先为图像命名,要拥有多少张图像,并按顺序显示,然后为每个图像分配名称。如果我必须重构原始代码,则外观如下:

#lang racket

(require 2htdp/image)

(define paths '("graphics/orc.png"
                "graphics/hydra.png"
                "graphics/slime.bmp"
                "graphics/brigand.bmp"
                "graphics/player.bmp"))

(match-define (list ORC HYDRA SLIME BRIGAND PLAYER-IMAGE)
  (map bitmap paths))
(define PIC-LIST (list ORC HYDRA SLIME BRIGAND))

(define w (apply max (map image-width PIC-LIST)))
(define h (apply max (map image-height PIC-LIST)))
(define FRAME (rectangle w h 'outline 'white))
(define TARGET (circle (- (/ w 2) 2) 'outline 'blue))

(match-define (list ORC-IMAGE HYDRA-IMAGE SLIME-IMAGE BRIGAND-IMAGE)
  (map (λ (img) (overlay img FRAME)) PIC-LIST))

请注意,这里有三个不同的变量列表,并且我们只对每个变量定义一次,因此代码重复被最小化了。