[plt-scheme] Introducing bindings in a macro
Doug Williams skrev:
> I'd like to introduce bindings in a macro. The commented code for
> with-my-struct is more what I would like to see, but it doesn't work,
> The uncommented code works, but is more complex and, well, uglier. Is
> there a clearer way (i.e. closer to the commented code) to write it?
If you introduce the following helper:
(begin-for-syntax
(define (unhygienic id)
(syntax-local-introduce
(syntax-local-get-shadower id))))
You can write:
(define-syntax (with-my-struct stx)
(syntax-case stx ()
((with-my-struct s
expr ...)
#`(let ((#,(unhygienic #'a) (my-struct-a s))
(#,(unhygienic #'b) (my-struct-b s))
(#,(unhygienic #'c) (my-struct-c s)))
expr ...))))
which is pretty close to the goal:
(define-syntax with-my-struct
(syntax-rules ()
((with-my-struct s
expr ...)
(let ((a (my-struct-a s))
(b (my-struct-b s))
(c (my-struct-c s)))
expr ...))))
Another options is:
(define-syntax (with-my-struct stx)
(syntax-case stx ()
((with-my-struct s
expr ...)
(with-syntax
([a (unhygienic #'a)]
[b (unhygienic #'b)]
[c (unhygienic #'c)])
#'(let ((a (my-struct-a s))
(b (my-struct-b s))
(c (my-struct-c s)))
expr ...)))))
which looks a little prettier.
Full code:
(module with-struct mzscheme
(provide (all-defined))
(define-struct my-struct (a b c))
(begin-for-syntax
(define (unhygienic id)
(syntax-local-introduce
(syntax-local-get-shadower id))))
(define-syntax (with-my-struct stx)
(syntax-case stx ()
((with-my-struct s
expr ...)
(with-syntax
([a (unhygienic #'a)]
[b (unhygienic #'b)]
[c (unhygienic #'c)])
#'(let ((a (my-struct-a s))
(b (my-struct-b s))
(c (my-struct-c s)))
expr ...)))))
(define-syntax (with-my-struct stx)
(syntax-case stx ()
((with-my-struct s
expr ...)
#`(let ((#,(unhygienic #'a) (my-struct-a s))
(#,(unhygienic #'b) (my-struct-b s))
(#,(unhygienic #'c) (my-struct-c s)))
expr ...))))
(define a 111)
(define b 222)
(define c 333)
(define (test-with-my-struct)
(let ((s (make-my-struct 1 2 3)))
(with-my-struct s
(printf "a = ~a, b = ~a, c = ~a~n" a b c))
(with-my-struct s
(let ([a 11] [b 22] [c 33])
(printf "a = ~a, b = ~a, c = ~a~n" a b c)))))
(test-with-my-struct)
)
--
Jens Axel Søgaard