> even though (class ...) expands into a function where method-list is

It does not expand into a function where method-list is defined because it
does not expand in that way. The macro "define/method" is called with the
given syntax and the macro operates on that syntax (it's just a procedure
that takes a syntax argument and evaluates to syntax) and where the macro
lives, "method-list" is neither defined nor given as part of use of the
syntax. So the macro introduces it's own "method-list", so something in the
background like "method-list7734", which isn't your "method-list" but since
the macro's own "method-list" doesn't exist, set! doesn't know what to do,
and you get an error. This is a combination of how procedures work and how
hygiene works in macros.

One way to manage this is to make it part of the syntax:
(define-syntax (define/method stx)
  (syntax-parse stx
    [(_ (name ML arg ...) body)
     #'(begin (define (name arg ...) body)
              (set! ML (cons `(name ,name) ML)))]))

(define (make-person name age)
  (define (obj arg)
    (define method-list '())
    (define/method (get-name method-list) name)
    (second (assq arg method-list)))
Then it expands as you expect, because it's operating on the syntax you
have given it.

Another way: the macro can be coerced to use an identifier which it doesn't
understand by breaking the hygiene barrier

define-syntax (define/method stx)
  (syntax-parse stx
    [(_ (name arg ...) body)
     (with-syntax ((ML (datum->syntax stx 'method-list)))
        #'(begin (define (name arg ...) body)
                 (set! ML (cons `(name ,name) ML))))]))
Now this macro assumes the identifier "method-list" exists in whatever
context the code expands in, which is the behavior you expect.

Normally we don't want to break hygiene. For instance, if a macro's code
introduced some temporaries like "num" or "x" or something, we wouldn't
want those temporaries to shadow or otherwise clobber some innocent
macro-user's own use of these identifiers. When we call a procedure like
"displayln" we don't need to worry that the author of the code used some
name for some local identifier. Since macros are just racket procedures,
too, the same reasoning applies: we don't want to worry that when we call a
macro it might use some name we've already used. In your case, this is your
exact intention, so racket allows you to break this protective mechanism


You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
For more options, visit

Reply via email to