[racket] a little macro exercise
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