[racket] generate-temporaries, gensym, etc.

From: Neil Van Dyke (neil at neilvandyke.org)
Date: Tue Nov 5 08:24:25 EST 2013

What's the current preferred way to generate unique identifiers in 
syntax transformers?  "generate-temporaries"?

Rest of this email is a long example that might not be relevant to the 
answer, so please disregard if it's not.

In the below example (which is an abstracted tiny piece of a real 
program), I'm introducing one identifier that I programmatically paste 
into two parts of the syntax.  In this case, I need only one variable, 
so I didn't need something "gensym"-like.  If, however, I wanted "foo" 
to put each "BAR.CODE" forms in its own binding clause of a single 
"let*" (or something like that), should I be generating multiple 
identifiers, and if so, should I be using "generate-temporaries" or 
something else?

#lang racket/base

(require (for-syntax racket/base
                      syntax/parse)
          syntax/parse)

(begin-for-syntax
   (define-syntax-class bar-sc
     #:attributes (CODE)
     (pattern EXPR
              #:attr CODE #'(lambda (x) (cons EXPR x)))))

(provide foo)
(define-syntax (foo stx)
   (syntax-parse stx
     ((_ BAR:bar-sc ...+)
      (let ((new-id #'top-arg))
        #`(lambda (#,new-id)
            #,(let loop ((bar-codes (attribute BAR.CODE))
                         (last-expr new-id))
                (if (null? bar-codes)
                    last-expr
                    (loop (cdr bar-codes)
                          #`(#,(car bar-codes) #,last-expr)))))))))

;; Example:
;; ((foo "arg1" "arg2" "arg3") "seed")
;;=expand=>
;; ((lambda (top-arg)
;;    ((lambda (x) (cons "arg3" x))
;;     ((lambda (x) (cons "arg2" x))
;;      ((lambda (x) (cons "arg1" x))
;;       top-arg))))
;;  "seed")
;;=result=> ("arg3" "arg2" "arg1" . "seed")

Thanks,
Neil V.


Posted on the users mailing list.