#|An update: here is what the macro looks like now.|# (define-syntax (define-property stx) (define make-id (lambda (template . ids) (define str (apply format template (map syntax->datum ids))) (datum->syntax stx (string->symbol str)))) (syntax-parse stx [((~literal define-property) name:id init-value) (with-syntax ([getter-name (make-id "get-~a" #'name)] [setter-name (make-id "set-~a" #'name)]) #'(begin (define name init-value) (define/public (setter-name value) (set! name value)) (define/public (getter-name) name)))] [((~literal define-property) name:id init-value ((~literal get:expr) get-body)) (with-syntax ([getter-name (make-id "get-~a" #'name)]) #'(begin (define name init-value) (define/public (getter-name) get-body)))] [((~literal define-property) name:id init-value ((~literal set) (setter-vars:id ...) set-body:expr)) (with-syntax ([setter-name (make-id "set-~a" #'name)]) #'(begin (define name init-value) (define/public (setter-name setter-vars ...) set-body)))] [((~literal define-property) name:id init-value ((~literal get) get-body) ((~literal set) (setter-bindings:id ...) set-body:expr))
(with-syntax ([getter-name (make-id "get-~a" #'name)] [setter-name (make-id "set-~a" #'name)]) #'(begin (define name init-value) (define/public (setter-name setter-bindings ...) set-body) (define/public (getter-name) get-body)))])) Somewhat like http://msdn.microsoft.com/en-US/library/w86s7x04%28v=vs.80%29.aspx, but with mandatory initialization expressions for each property. -Patrick On 25 April 2012 10:10, Asumu Takikawa <as...@ccs.neu.edu> wrote: > On 2012-04-25 03:19:46 -0400, Patrick Mahoney wrote: > > I'm looking to define a macro that extends the forms within a > racket/class > > class%. In particular, I would like a form to define a C# like class > > language form property, that implements the getters and setters for an > > initialized field automatically. > > FYI, `get-field` and `set!-field` already allow you to get and set any > public fields on an object. > > > (define-syntax (define-property syntax) > > (syntax-parse syntax > > [((~literal define-property) name:id init-value) > > > > #'(define name init-value) > > (define/public (set-name! init-value) > > (set! name init-value)) > > (define/public (get-name) > > name)])) > > So this macro won't quite work as written. Here's an alternative that > will at least run (but still won't work as you expect): > > (define-syntax (define-property stx) > (syntax-parse stx > [(_ name:id init-value) > #'(begin (define name init-value) > (define/public (set-name! new-val) > (set! name new-val)) > (define/public (get-name) name))])) > > One issue was that you were using `syntax` as the argument to this > transformer, which won't work because you end up shadowing > `syntax`, which is needed to write the template. I changed it to `stx`. > > Secondly, you need to use `begin` to splice all of the definitions > together. > > Note that this still doesn't work though. The `set-name!` and `get-name` > will be introduced as is (or hygienically renamed) and won't use the > name of the field as you might want. To do that, you might want to write > `define-property` so that it takes get/set method names as arguments.[1] > > [1]: otherwise you need to unhygienically introduce a binding, which > is best to avoid unless you know what you are doing. > > > define/public: use of a class keyword is not in a class top-level in: > > (define/public (set-name! init-value) (set! name init-value)) > > You probably got this error by trying out the macro outside of a class > or because you weren't splicing the definition quite right. > > Cheers, > Asumu >
____________________ Racket Users list: http://lists.racket-lang.org/users