While reading *rackunit* source I stumbled on a pattern that I can't figure 
out. Why the heck does it work? Condensed to its essence it amounts to 
introducing indirection with a macro-generated define:

#lang racket
> (require (for-syntax syntax/parse)
>          syntax/parse/define)

 


> (define-simple-macro (define-foo (name:id formal:id ...) body:expr ...)
>   (begin
>     (define (foo-impl formal ...) body ...)
>     (define-syntax (name stx)
>       (syntax-parse stx
>         [(_ . args) #'(foo-impl . args)]
>         [_:id #'(λ args (apply foo-impl args))]))))

 


> (define-foo (bar op a b) (op a b))
> (define-foo (baz op a b) (op a b))
> ;; Why am I not getting this error?
> ;; --------------------------------
> ; module: identifier already defined
> ;   at: foo-impl



See that *foo-impl* there? The same name is being reused every time the 
*define-foo* macro is called. I would've expected Racket to shout at me 
that I'm attempting to redefine something, but it doesn't and magically it 
works. Why? Say, in Elisp or Clojure I would've gensymed that symbol. What 
am I missing? Does Racket perform some clever renaming to preserve hygiene 
or something? Could someone please help me reason through this.

Original source: 
https://github.com/racket/rackunit/blob/master/rackunit-lib/rackunit/private/check.rkt#L110

PS: also I left that second clause there just cause it just dawned on me 
how cool it is that we can use macros in identifier position :)

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to