[plt-scheme] Controlling execution in macro defining macros

From: Ryan Culpepper (ryan_sml at yahoo.com)
Date: Wed Jun 23 16:49:50 EDT 2004

--- Noel Welsh <noelwelsh at yahoo.com> wrote:
>   For list-related administrative tasks:
>   http://list.cs.brown.edu/mailman/listinfo/plt-scheme
> I am writing a macro A that expands into the definition of
> a macro B.  When macro B is called I want it to expand
> into a function that stashes away the values of its
> parameters and then executes some expressions specified
> when A was called.  I want the parameters to B to be
> executed only once, and this is proving to be difficult.
> Attached in some code that indicates the difficulty I am
> facing.
> If I uncomment 1 the code fails because stash-it isn't in
> the same environment as B.
> If I uncomment 2 the parameters are evaluated multiple
> times
> If I uncomment 3 (and comment out the line below it) the
> code fails because foo isn't defined in the expander
> environment.
> I've tried a number of other variations and they all fail
> for some reason or other.  Any suggestions from the
> assembled macrology experts?  It is crucial that the macro
> A expands into another macro definition (B), that calls to
> A may declare expressions defined in the execution
> environment, and that the parameters to B are executed
> once.

I think you just need to create a let-bound variable to hold the
evaluated parameter list and then use that variable. Your code is
duplicating the expression code by using the inner macro's pattern
variables multiple times. Here's how I would write a:

;; (a identifier (identifier ...) expression) : macro definition
;; a defines a procedure-like macro which has the side effect of 
;; stashing away its arguments.
(define-syntax a
  (syntax-rules ()
    ((_ name (formal ...) expr)
     (define-syntax name
       (syntax-rules ()
         ((_ actual (... ...))
          (let ((args (list actual (... ...))))
            (stash-it args)
            (apply (lambda (formal ...) expr) args))))))))

So (a b (x y) (+ x y)) will produce a macro definition that looks
like this:

(define-syntax b
  (syntax-rules ()
    ((_ actual ...)
     (let ((args (list actual ...))))
       (stash-it args)
       (apply (lambda (x y) (+ x y)) args)))))

Hope that solves your problem,

Do you Yahoo!?
Yahoo! Mail - 50x more storage than other providers!

Posted on the users mailing list.