I'm unclear why I'm getting an unbound-identifier error in this macro. I've 
written other self-referencing macros in the past that have worked, so I'm 
unclear why this one doesn't. 

What I expect is that when `definer` is called with one argument, the first 
branch of `syntax-case` will stick on a default argument and call `definer` 
again. Which it does, except that in that case, it only binds the name 'id' 
rather than both 'id' and 'arg-id'. 


#lang racket
(require (for-syntax racket/syntax) rackunit)

(define-syntax (definer stx)
  (syntax-case stx ()
    [(_ id)
     #'(definer id zam)]
    [(_ id arg)
     (with-syntax ([arg-id (format-id stx "~a-~a" #'arg #'id)])
       #'(begin
           (define id (quote id))
           (define arg-id (quote arg-id))))]))


(definer foo-id bar)
(check-equal? foo-id 'foo-id)
(check-equal? bar-foo-id 'bar-foo-id)

(definer baz-id)
(check-equal? baz-id 'baz-id)
(check-equal? zam-baz-id 'zam-baz-id) ;; unbound identifier error


OTOH, this version of the macro, which repeats the expansion template rather 
than calling itself, works fine:


#lang racket
(require (for-syntax racket/syntax) rackunit)

(define-syntax (definer2 stx)
  (syntax-case stx ()
    [(_ id)
     (with-syntax ([arg-id (format-id stx "~a-~a" (format-id stx "zam") #'id)])
       #'(begin
           (define id (quote id))
           (define arg-id (quote arg-id))))]
    [(_ id arg)
     (with-syntax ([arg-id (format-id stx "~a-~a" #'arg #'id)])
       #'(begin
           (define id (quote id))
           (define arg-id (quote arg-id))))]))


(definer2 foo-id bar)
(check-equal? foo-id 'foo-id)
(check-equal? bar-foo-id 'bar-foo-id)

(definer2 baz-id)
(check-equal? baz-id 'baz-id)
(check-equal? zam-baz-id 'zam-baz-id) ;; no error this time
____________________
  Racket Users list:
  http://lists.racket-lang.org/users

Reply via email to