[racket] Macro defining functions question
Kevin Forchione wrote:
> This one leaves me scratching my head. Why doesn’t this work? When you
> run the macro the functions aren’t defined outside of the extent of
> the begin.
> (define-syntax (foo stx)
> (syntax-case stx ()
> [(foo)
> #'(begin
> (define (bar x) x)
> (define (baz x) x))]))
> After inning the macro (bar 3) produces an bar undefined error.
After the your definition of the syntax FOO, you can think of:
(foo) ;this is the syntax use
as expanding to:
(begin
(define (G0 G2) G2)
(define (G3 G4) G4)) ;this is the output form
that is: all the identifiers in binding position and reference position
introduced in the syntax-use's output-form have been renamed to unique
gensyms; there are no bindings with name BAR and BAZ in the lexical
context of the syntax use.
Instead, if you do:
(define-syntax (foo stx)
(syntax-case stx ()
[(foo)
(datum->syntax #'foo
'(begin
(define (bar x) x)
(define (baz x) x)))]))
(foo)
(bar 1)
(baz 2)
everything works because DATUM->SYNTAX transforms all the symbols in the
symbolic expression into identifiers belonging to the lexical context of
the syntax use. Such definition is equivalent to:
(define-syntax (foo stx)
(syntax-case stx ()
[(foo ?stuff)
#'?stuff]))
(foo (begin
(define (bar x) x)
(define (baz x) x)))
(bar 1)
(baz 2)
Usually, to introduce unhygienic bindings in the lexical context of
the syntax use, one does:
(define-syntax (foo stx)
(syntax-case stx ()
[(foo)
(with-syntax
((BAR (datum->syntax #'foo 'bar))
(BAZ (datum->syntax #'foo 'baz)))
#'(begin
(define (BAR x) x)
(define (BAZ x) x)))]))
(foo)
(bar 1)
(baz 2)
so that only BAR and BAZ are marked as belonging to the lexical context
of the syntax use. Such definition is equivalent to:
(define-syntax (foo stx)
(syntax-case stx ()
[(foo ?bar ?baz)
#'(begin
(define (?bar x) x)
(define (?baz x) x))]))
(foo bar baz)
(bar 1)
(baz 2)
which is the "correct" way of doing things because: first it creates the
identifiers BAR and BAZ in the lexical context of the syntax use; second
it composes the output form with such identifiers, without breaking
hygiene.
HTH
--
Marco Maggi