[plt-scheme] macro question

From: Michael Vanier (mvanier at cs.caltech.edu)
Date: Sat Jun 7 06:02:35 EDT 2008

But don't you mean datum->syntax-object, not datum->syntax?

Michael Vanier wrote:
> 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 
>>
> _________________________________________________
>  For list-related administrative tasks:
>  http://list.cs.brown.edu/mailman/listinfo/plt-scheme


Posted on the users mailing list.