[plt-scheme] expand vs. local-expand; make-syntax-mapping

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Thu Jul 17 08:34:41 EDT 2003

At Wed, 16 Jul 2003 17:05:46 -0400 (EDT), Doug Orleans wrote:
> I'm still unclear about all the differences between `expand' and
> `local-expand'.  Why doesn't `expand' allow a stop-list?

Part of the answer is that `local-expand' doesn't work when
`letrec-syntaxes+values' is absent from the stop list. I knew this
once, but forgot until now.

The `expand' procedure expands its argument as a top-level expression.
It expands completely, so that the result has no local syntax bindings.

The `local-expand' procedure expands its argument as a subexpression in
the currently expanded expression's context. In particular, if the
expression being expanded is inside a `let-syntax', then the
`let-syntax' bindings apply when expanding the expression passed to

If the stop list is not empty, then `local-expand' can't throw away
local syntax bindings, because they might be used inside the places
where expansion stopped. But this is where things start to go wrong...

Here's an example of a `local-expand' gone wrong:

  > (define-syntax (s stx)
      (syntax-case stx () 
         [(_ x) (local-expand #'x (syntax-local-context) null)]))
  > (s (let ([x 10]) (let-syntax ([foo (lambda (stx) #'x)]) foo)))
  compile: identifier used out of context in: x

This goes wrong for the same reason that `expand-once' goes wrong. It's
an interaction between the "marks" and "renamings" used to track scope.

I don't think the problem can be solved by having a
`local-expand-completely' that expands more like `expand', because the
`expand' technique relies on having the enture top-level expression.

So we're stuck again guess, unless you know that a `local-expand'ed
subexpression will have no local macros that introduce uses of local
variables. In that restricted case, you can throw out the syntax part
of each `letrec-syntaxes+values' to get to "primitive" syntax.

> Third, what's the deal with `make-syntax-mapping'? Why is the numeric
> argument not wrapped in #%datum?

The expander doesn't bother expanding the RHSs of local syntax
bindings. It just evaluates them, on the theory that they won't show up
with `expand', and they won't be useful with `expand-once' or


Posted on the users mailing list.