[plt-scheme] (require... ) expanded from a macro

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Sat Oct 21 19:39:56 EDT 2006

At Sat, 21 Oct 2006 15:52:44 +0200, Jens Axel Søgaard wrote:
> To break hygiene use syntax-local-introduce:
> 
>    (define-syntax (require-extension stx)
>      (syntax-case stx (srfi)
>        ((_ (srfi n))
>         (number? (syntax-e #'n))
>         (let ([n (syntax-e #'n)])
>           (with-syntax ([name (format "~a.ss" n)])
>             (syntax-local-introduce
>              #'(require (lib name "srfi"))))))))

In this case, I recommend `datum->syntax-object', instead:

   (define-syntax (require-extension stx)
     (syntax-case stx (srfi)
       ((_ (srfi n))
        (number? (syntax-e #'n))
        (with-syntax ([path (datum->syntax-object
                             #'n
                             `(lib ,(format "~a.ss" (syntax-e #'n)) 
                                   "srfi"))])
           #'(require path)))))

The `datum->syntax-object' function is more standard and easier to
reason about. The above use makes `(lib "n.ss" "srfi")' have the same
lexical context as the original `n', instead of the context of
macro-introduced syntax. That way, the bindings introduced by `(lib
"n.ss" "srfi")' will bind in the same context where `n' would have
bound.


`syntax-local-introduce' is a low-level feature that I still only know
how explain in operational terms (i.e., in terms of the "marks" and
"renamings" used for syntax-case).

My main use of `syntax-local-introduce' is when a macro is itself
playing the role of a macro expander. For example, the
`define-fun-syntax' macro in `(lib "foreign.ss")' cooperates with `fun'
to macro-expand a sub-language of foreign-function types.

Looking at other uses of `syntax-local-introduce' in our code bas, the
ones in the "parser-tools" collection are the same sort of use as in
`(lib "foreign.ss")'. The ones in the teaching languages are also
similar: they bridge the gap between restricting procedure definition
uses to first-order positions in the beginner language, but allowing
them as arguments to higher-order teachpack primitives, such as
`on-tick-event'.

A few uses are with syntax properties like 'disappeared-use, which
Check Syntax consults for drawing arrows; in that case, the problem is
that syntax properties are somewhat hidden from the macro-expansion
mechanism, so the macro is forced to do a bit of the macro-expander's
job. Finally, I see a lot of uses in `(lib "package.ss")', which is
still terribly broken.

In short, use `syntax-local-introduce' when you are cooperating closely
with the macro expander or managing the macro-expansions of a
sub-language. I think you should probably avoid it, otherwise.

I'm not certain that I've given this advice consistently, in part
because I'm not entirely sure of the uses myself. Indeed, I'd prefer to
get rid of `syntax-local-introduce', but something better seems to be
missing in our syntax system, so that `syntax-local-introduce'
sometimes seems necessary.

Matthew



Posted on the users mailing list.