[racket] a little macro exercise

From: Carl Eastlund (cce at ccs.neu.edu)
Date: Sat Oct 9 09:52:34 EDT 2010

Here's my solution.  It is pure (if you ignore the set! nature of
letrec), has linear expansion, avoids multiple values, and uses a
single "case" for conditional tests.  The only thing it lacks that I
know of is support for "else".

--------------------------------------------------------------------------------
#lang racket
(require (for-syntax syntax/parse) racket/stxparam)

(define-syntax-parameter break
  (lambda (stx) (raise-syntax-error #f "used outside of cas-cad-e" stx)))

(define-syntax cas-cad-e
  (syntax-parser
    [(_ e:expr [(v ...) body:expr ...+] ...)
     (with-syntax ([(id ...) (generate-temporaries #'((v ...) ...))])
       (with-syntax ([(f ...) #'(start id ... finish)]
                     [(action ...) #'((begin) (begin body ...) ... (begin))]
                     [(next ...) #'(id ... finish void)])
         #'(let/ec escape
             (syntax-parameterize ([break (make-rename-transformer #'escape)])
               (letrec ([f (lambda () action (next))] ...)
                 (case e [(v ...) (id)] ...))))))]))

(define (nursery-rhyme n)
  (cas-cad-e n
    [(1 2) (displayln "buckle my shoe")]
    [(3 4) (displayln "shut the door") (break)]
    [(5 6) (displayln "pick up sticks")]
    [(7 8) (displayln "lay them straight") (break)]
    [(9 10) (displayln "a big fat hen")]))

(for ([i '(1 2 3 4 5 6 7 8 9 10)])
  (nursery-rhyme i))
--------------------------------------------------------------------------------

Carl Eastlund


Posted on the users mailing list.