[plt-scheme] Introducing bindings in a macro

From: Jens Axel Soegaard (jensaxel at soegaard.net)
Date: Thu Jan 17 15:49:06 EST 2008

Doug Williams skrev:
> I'd like to introduce bindings in a macro.  The commented code for 
> with-my-struct is more what I would like to see, but it doesn't work,  
> The uncommented code works, but is more complex and, well, uglier.  Is 
> there a clearer way (i.e. closer to the commented code) to write it? 

If you introduce the following helper:

   (begin-for-syntax
     (define (unhygienic id)
       (syntax-local-introduce
        (syntax-local-get-shadower id))))

You can write:

   (define-syntax (with-my-struct stx)
     (syntax-case stx ()
       ((with-my-struct s
          expr ...)
        #`(let ((#,(unhygienic #'a) (my-struct-a s))
                (#,(unhygienic #'b) (my-struct-b s))
                (#,(unhygienic #'c) (my-struct-c s)))
            expr ...))))

which is pretty close to the goal:

    (define-syntax with-my-struct
      (syntax-rules ()
       ((with-my-struct s
         expr ...)
        (let ((a (my-struct-a s))
              (b (my-struct-b s))
              (c (my-struct-c s)))
          expr ...))))

Another options is:

   (define-syntax (with-my-struct stx)
     (syntax-case stx ()
       ((with-my-struct s
          expr ...)
        (with-syntax
            ([a   (unhygienic #'a)]
             [b   (unhygienic #'b)]
             [c   (unhygienic #'c)])
          #'(let ((a (my-struct-a s))
                  (b (my-struct-b s))
                  (c (my-struct-c s)))
              expr ...)))))

which looks a little prettier.



Full code:


(module with-struct mzscheme

   (provide (all-defined))

   (define-struct my-struct (a b c))

   (begin-for-syntax
     (define (unhygienic id)
       (syntax-local-introduce
        (syntax-local-get-shadower id))))

   (define-syntax (with-my-struct stx)
     (syntax-case stx ()
       ((with-my-struct s
          expr ...)
        (with-syntax
            ([a   (unhygienic #'a)]
             [b   (unhygienic #'b)]
             [c   (unhygienic #'c)])
          #'(let ((a (my-struct-a s))
                  (b (my-struct-b s))
                  (c (my-struct-c s)))
              expr ...)))))

   (define-syntax (with-my-struct stx)
     (syntax-case stx ()
       ((with-my-struct s
          expr ...)
        #`(let ((#,(unhygienic #'a) (my-struct-a s))
                (#,(unhygienic #'b) (my-struct-b s))
                (#,(unhygienic #'c) (my-struct-c s)))
            expr ...))))

   (define a 111)
   (define b 222)
   (define c 333)

   (define (test-with-my-struct)
     (let ((s (make-my-struct 1 2 3)))
       (with-my-struct s
         (printf "a = ~a, b = ~a, c = ~a~n" a b c))
       (with-my-struct s
         (let ([a 11] [b 22] [c 33])
           (printf "a = ~a, b = ~a, c = ~a~n" a b c)))))

   (test-with-my-struct)

   )


-- 
Jens Axel Søgaard


Posted on the users mailing list.