我想做这样的事情:
(define-field-magic color car)
(set! color "green")
(pretty-display color)
而不是这个:
(set-field! color car "green")
(pretty-display (get-field color car))
我想做这样的事情:
(define-field-magic color car)
(set! color "green")
(pretty-display color)
而不是这个:
(set-field! color car "green")
(pretty-display (get-field color car))
改编自The Racket Guide的一种解决方案是:
(define-syntax color
(syntax-id-rules (set!)
[(set! color e) (set-field! color car e)]
[(clock a ...) ((get-field color car) a ...)]
[clock (get-field color car)]))
但可能有更好、更易读的方法。
这是对标题中问题的回答。
以下解决方案适用于公共领域。请注意,来自球拍/平局的 color% 字段是私有的。出于这个原因,我在下面定义了我自己的 color% 类:
#lang racket
(define color%
(class object%
(init-field [r 0]
[g 0]
[b 0]
[a 1.0])
(super-new)))
(define-syntax-rule (define-local id class-expr field-id object-expr)
(begin
(define get (class-field-accessor class-expr field-id))
(define put! (class-field-mutator class-expr field-id))
(define-syntax id
(syntax-id-rules (set!)
[(set! id e) (put! object-expr e)]
[id (get object-expr)]))))
(define a-color (make-object color% 255 255 255 1.0))
(define-local red color% r a-color)
(define-local blue color% g a-color)
(define-local green color% b a-color)
red
(set! red 125)
red
输出是:
255
125
One way to do something similar to what you want, without having to use macros, is via SRFI 17:
(require srfi/17)
(define (bind-field field obj)
(getter-with-setter
(lambda ()
(dynamic-get-field field obj))
(lambda (val)
(dynamic-set-field! field obj val))))
Now, you can do this (I renamed your object from car
to obj
, since car
is a built-in function and you don't want to shadow that):
(define color (bind-field 'color obj))
(set! (color) "green")
(pretty-display (color))
基于安德烈斯的回答 - 我赞成 - 但可能更惯用:
(define-syntax color
(syntax-id-rules (set!)
[(set! id e) (set-field! color car e)]
[(id a ...) ((get-field color car) a ...)]
[id (get-field color car)]))