[racket] datum<->syntax with same context, yet "unbound identifier"

From: Tobias Hammer (tobias.hammer at dlr.de)
Date: Wed Nov 21 10:23:31 EST 2012

On Wed, 21 Nov 2012 15:33:06 +0100, Greg Hendershott  
<greghendershott at gmail.com> wrote:

>> The lexical context you're picking up to put on #'args in the lam
>> macro is the context that's sitting on the parentheses in the first
>> argument to 'lam' in the body of 'expand-to-lam'. that context has no
>> "x" bound.
> OK, that explains why x is not bound. Thanks!
>> This is the trouble with these kinds of macros: you have to be careful
>> to propagate the correct lexical information thru. In this case, you
>> can either change expand-to-lam to carry its argument's lexical
>> context onto that open paren there or you can change lam to use a
>> different spot to get its lexical information (one that's already
>> being carried thru, eg the context on the actual variables for
>> example).
> I want lam to be usable by other macros without the latter needing to
> cooperate explicitly; I want them to "just work". So I prefer the
> second way.

As Robby explained you are using the context of the list of args for all  
which is in this case a wrong one. One context that should be valid in all  
in your example is the one of the arguments itself. If you unpack the
arguments, do whatever you want to them and then reapply the context you  
stripped before,
it should (as far as i understand) work:

(define-syntax (lam stx)
   (syntax-case stx ()
     [(_ args body ...)
      (with-syntax ([conv-args (for/list ([a (syntax->list #'args)])
                                 (define a-datum (syntax->datum a))
                                 ;; do whatever you want with a-datum
                                 (datum->syntax a a-datum))])
      #`(lambda conv-args
          body ...))]))

Other macros only have to cooperate in the 'normal' way, i.e. they have to  
make sure
that the arguments they pass in have the right context.


Posted on the users mailing list.