[plt-scheme] macro question
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
>