[racket] macros in local namespaces?...

From: Ryan Culpepper (ryan at cs.utah.edu)
Date: Wed Feb 1 12:11:55 EST 2012

On 02/01/2012 09:45 AM, Rüdiger Asche wrote:
> Hi there,
>
> I'm trying to get a grip on macros. Here is a very simple Racket expression  (1):
>
> (letrec [(a 2)
>          (b 3)
>          (afn (lambda (x) (+ x a)))
>          (bfn (lambda (x) (+ x b)))]
>    (afn (bfn 2)))
>
> Now I need a syntactic abstraction for afn and bfn. The following will do in first approximation (2):
>
> (define-syntax-rule (absfn varname) (lambda (x) (+ x varname)))
>
> (letrec [(a 2)
>          (b 3)
>          (afn (absfn a))
>          (bfn (absfn b))]
>    (afn (bfn 2)))
>
>
> However, it will fail due to scoping rules in the following example (3):
>
> (define-syntax-rule (absfn varname) (lambda (x) (+ (+ x localc) varname)))
>
> (letrec [(a 2)
>          (b 3)
>          (localc 4)
>          (afn (absfn a))
>          (bfn (absfn b))]
>    (afn (bfn 2)))
>
> In other words, my syntactic extension absfn needs to be embedded in the namespace of the sorrounding expression (or as a "dumb" macro which simply does lexical replacement without considering scoping, but needless to say such a macro would be unhygienic).
> I suspect that letrec-syntax was meant for that purpose, but I can't figure out how the parameters to define-syntax-rule would translate to those of letrec-syntax.
>
> Does anyone have sample code for how to get (3) above to work?
>
> Thanks!

The easiest way is to use internal definitions instead:

(let ()
   (define a 2)
   (define b 3)
   (define localc 4)
   (define-syntax-rule (absfn varname)
     (lambda (x) (+ (+ x localc) varname)))
   (define afn (absfn a))
   (define bfn (absfn b))
   (afn (bfn 2)))

Another way is to use letrec-syntaxes+values, as Matthias answered.

Ryan

Posted on the users mailing list.