[racket] Onlisp's condlet macro in Racket

From: Eli Barzilay (eli at barzilay.org)
Date: Thu Jan 3 13:08:47 EST 2013

Yesterday, Sean Kanaley wrote:
> 
> My understanding from the linked blog is Racket uses phases so
> e.g. changing functions at REPL like (set! remove-duplicates-by 3)
> that might be used in macros called after this don't use the new
> binding.  But if I define a global run-time function, can't it be
> renamed in the macro phase as <function_name>_1, in the same way
> macros perform renaming as shown in the swap! example from the
> official docs?  Now when I run-time set <function_name> to 5, it's
> still using <function_name>_1 and so does not affect macro
> expansion.  If explaining it is too tedious or too above my current
> understanding feel free to say as much.

The general idea is that each level (runtime and macro) use their own
world, so you need to do the changes that you want to at the
appropriate level.  In any case, something that wasn't mentioned so
far is that you can just use the `remove-duplicates' function instead
of implementing it from scratch -- here's Mattias's code, revised to
use it.  The require at the macro level is needed since the `racket'
language has only `racket/base' available at the syntax level.

(require (for-syntax racket/list))

(define-syntax (condlet stx)
  (syntax-case stx ()
    [(condlet ((c (x e) ...) ...) body ...)
     (let* ((vars (remove-duplicates (syntax->list #'(x ... ...))
                                     free-identifier=?))
            (nils (map (lambda (c) #''()) vars)))
       #`(cond
           [c ((lambda #,vars
                  (let ((x e) ...)
                    body ...))
                #, at nils)]
           ...))]))


-- 
          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                    http://barzilay.org/                   Maze is Life!

Posted on the users mailing list.