[plt-scheme] Macros in the same module

From: Eli Barzilay (eli at barzilay.org)
Date: Thu May 7 19:10:20 EDT 2009

On May  7, Paulo J. Matos wrote:
> This is what currently is happening to my macro:
> #lang scheme
> (define-for-syntax (bar a)
>   (syntax-case a ()
>     [(_ name val)
>      #'(define name val)]))
> (define-syntax (foo a)
>   (syntax-case a ()
>     [(_ name val)
>      #'(bar name val)]))
> (foo a 42)
> expand: unbound identifier in module in: bar
> I never really looked very deeply into syntax-case but from what I can
> see now, #' transforms an s-expr into syntax which will represent the
> final code.

It doesn't "transform" -- it's rather like writing a piece of syntax,
like the other values that the macro function is dealing with.

> It doesn't transform bar because bar is another macro,

No, `bar' is a function.  But more importantly, you have it inside a
#' which means that it's a piece of quoted syntax and the quoted
syntax is something that lives in the runtime world, and there is no
`bar' there.  Here's a version that works:

  (define-for-syntax (bar a)
    (syntax-case a ()
      [(_ name val)
       #'(define name val)]))
  (define-syntax (foo a)
    (syntax-case a ()
      [(_ name val)
       (bar #'(whatever name val))]))

Note that here `bar' is used as a function, but it's a function in the
syntax world.  Here's a version that works like Noel mentioned (IIRC):

  (define-syntax (bar a)
    (syntax-case a ()
      [(_ name val)
       #'(define name val)]))
  (define-syntax (foo a)
    (syntax-case a ()
      [(_ name val)
       #'(bar name val)]))

In here, `foo' (at compile time) doesn't really call `bar' -- it just
expands to some syntax with `bar', and syntax expansion will proceed
to expand the resulting syntax and will call `bar' for that, which
eventually achieves the same effect in this case.  (BTW, this can be
considered that `foo' is calling `bar', only it doesn't use the normal
function call protocol.)  The second version is somewhat more common
since you can often get away with just simlpe `syntax-rules', and the
first version is a little better if `bar' should not exist at the
runtime level.  The second version is also more common when you want
to perform some computations at the syntax level that go beyond the
common Syntax -> Syntax functions.

> but if I try to
> #, bar it doesn't work either saying:
>  expand: unbound identifier in module in: a

If you're new to `syntax-case' macros, I think it's better to avoid #`
and #, for now, it will make things more confusing.

> Now, from the stepper I get the transformed expression:
> (module page scheme (define-for-syntax (bar a) (syntax-case a () ((_
> name val) (syntax (define name val))))) (define-syntax (foo a)
> (syntax-case a () ((_ name val) (quasisyntax ((unsyntax bar) name
> val))))) (#<procedure> a 42))
> Which is strange because either the procedure is bar (which is strange
> because it is not defined), or it is define which is even stranger
> because define is not a procedure.

(My guess is that the above is a result of trying #` and #,)

          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                  http://www.barzilay.org/                 Maze is Life!

Posted on the users mailing list.