[plt-scheme] macro question

From: Michael Vanier (mvanier at cs.caltech.edu)
Date: Sat Jun 7 05:59:49 EDT 2008

Thanks very much!

Jos Koot wrote:
> 'es' introduced in the macro is not identified with the local variable 
> 'es' of the environment from which the macro is called. This is 
> hygienic. The hygienic behaviour avoids unintentional identifications. 
> Besides there might also hang around a global variable of the same name, 
> in which case your macro would identify 'es' with the global variable, 
> not the local one. Below two solutions, the first one non hygienic, the 
> second one hygienic by requiring the variable to be mentioned in the 
> macro call. In general hygienic solutions are to be preferred, I think.
> Jos
> 
> (define-syntax (get-stack-vals stx)
>   (syntax-case stx ()
>   ((_ n (env first rest) expr ...)
>    #`(let*-values (((env stk) (es-values #,(datum->syntax stx 'es)))
>                    ((first rest) (take n stk)))
>        expr ...))))
> 
> (define-syntax get-stack-vals
>   (syntax-rules ()
>   ((_ n (env first rest) es expr ...)
> ;                              ^^^
>    (let*-values (((env stk) (es-values es))
>                    ((first rest) (take n stk)))
>        expr ...))))
> 
> ----- Original Message ----- From: "Michael Vanier" 
> <mvanier at cs.caltech.edu>
> To: "mzscheme Mailing List" <plt-scheme at list.cs.brown.edu>
> Sent: Saturday, June 07, 2008 11:17 AM
> Subject: [plt-scheme] macro question
> 
> 
>> I've run into a problem with a macro I don't know how to solve.  
>> Here's the macro:
>>
>> (define-syntax get-stack-vals
>>   (syntax-rules ()
>>     ((_ n (env first rest) expr ...)
>>      (let*-values (((env stk) (es-values es))
>>                    ((first rest) (take n stk)))
>>        expr ...))))
>>
>> Here's a use:
>>
>> (define (do-def es)
>>   (get-stack-vals 2 (env first rest)
>>      (let ((sym (cadr first))
>>            (val (car first)))
>>        (if (symbol? sym)
>>            (let ((env2 (env-add env sym val)))
>>              (make-es env2 rest))
>>            (error "cannot define non-symbol: " sym)))))
>>
>> which should expand to:
>>
>> (define (do-def es)
>>   (let*-values (((env stk) (es-values es))
>>                 ((first rest) (take 2 stk)))
>>     (let ((sym (cadr first))
>>           (val (car first)))
>>       (if (symbol? sym)
>>           (let ((env2 (env-add env sym val)))
>>             (make-es env2 rest))
>>           (error "cannot define non-symbol: " sym)))))
>>
>> and apparently does, at least according to the macro stepper.  
>> However, when I call do-def I get an error message: "reference to 
>> undefined identifier: es".  This seems odd, because es is in scope at 
>> the macro expansion location.  Is the es in the get-stack-vals macro 
>> bound in the lexical scope of that macro?  All the other external 
>> identifiers in the macro are bound at the top-level, so it works 
>> either way for them.  If this is the case, how do I get es to be bound 
>> the way I want it to be?  I realize that I'm trying to do something a 
>> bit naughty since I'm assuming a binding for es will exist at all 
>> macro expansion locations; alternative suggestions are welcome (other 
>> than "don't give up your day job").
>>
>> I'm a macro newbie, so please be gentle ;-)  PLT Scheme's macro system 
>> is an intricate and beautiful thing that I'm just beginning to wrap my 
>> head around.
>>
>> Mike
>>
>>
>> _________________________________________________
>>  For list-related administrative tasks:
>>  http://list.cs.brown.edu/mailman/listinfo/plt-scheme 
> 


Posted on the users mailing list.