[plt-scheme] (require... ) expanded from a macro
At Sun, 22 Oct 2006 07:58:12 +0300, "Dan Muresan" wrote:
> (define-syntax require-library
> (lambda (stx)
> (define libraries '()) ;; broken, should be outside lambda
> (syntax-case stx (quote)
> ((_ (quote lib))
> (let ((slib (syntax-object->datum #'lib)))
> (if (memv slib libraries)
> (syntax (begin))
> (let ((str (string-append
> (symbol->string
> (syntax-e #'lib)) ".scm")))
> (set! libraries (cons slib libraries))
> (display (format "Including ~a\n" slib))
> (with-syntax ((fname (datum->syntax-object #'lib str)))
> #'(include fname)))))))))
>
> (require-library 'x) ;; should expand to (include "x.scm")
> ;; x.scm just contains (define (f x) x)
>
> f ;; raises "undefined identifier"
>
> The macro runs, but the binding for f seems to be hidden.
>
> Firstly, why are the included bindings hidden?
Mostly the same as before. The `fname' trick didn't work because
`include' (more or less arbitraily) uses the whole `(include fname)'
context for the included code, instead of just `fname'.
In this case, you can use
(with-syntax ([str str])
(include-at/relative-to lib lib str))
which causes `str' to be resolved relative to the source of `lib', and
also makes the inserted code have the context of `lib'.
In other words, since `include' is commonly inserted by macros, we
offer a variant that more directly supports macros.
> And, secondly, where
> should I put the "libraries" catalog (inside (lambda (stx) ...) is
> obviously broken, but putting them outside generates an error)?
Writing it as
(define-syntax require-library
(let ([libraries '()])
(lambda (stx)
...)))
probably works for your purposes.
It doesn't work right with separate compilation, but I'm guessing that
separate compilation is not an issue.
Matthew