[racket] Macro Help

From: Brian Mastenbrook (brian at mastenbrook.net)
Date: Mon Feb 27 11:42:05 EST 2012

On 02/26/2012 07:39 PM, Neil Van Dyke wrote:
> Helmut Rohrbacher wrote at 02/26/2012 07:18 PM:
>> What macro voodoo do I need to harness in order to be able to
>> implement the first definition syntax where the /args ... -> body/
>> segments need not be wrapped in parens?
> I think that the difficulty is due to using old "syntax-rules".
> Nowadays, "syntax-rules" is a hobby for the patient, like building model
> ships in bottles.

Ships in bottles? Great fun! [1]

This one isn't so hard if you allow yourself some helper macros. The 
idea is to walk over the body, searching for the literal -> followed by 
the value expression. As you walk, accumulate what precedes the ->, and 
when you find it, create a list of the accumulator and the value 
expression and accumulate it into another list of pattern/value lists. 
When you run out of body, pass that pattern/value list accumulator to a 
third macro.

As always, DrRacket's macro stepper is very useful for these kinds of 

Here it is in code:

(define-syntax function
   (syntax-rules ()
     ((_ body ...)
      (function-accumulate () () (body ...)))))

(define-syntax function-accumulate
   (syntax-rules (->)
     [(_ () (pattern/value-list ...) ())
      (function^ pattern/value-list ...)]

     [(_ (pattern ...) (pattern/value-list ...) (-> value body ...))
      (function-accumulate ()
                           (pattern/value-list ...
                            [(pattern ...) value])
                           (body ...))]

     [(_ (pattern ...) (pattern/value-list ...) (pattern-expr body ...))
      (function-accumulate (pattern ... pattern-expr)
                           (pattern/value-list ...)
                           (body ...))]))

(define-syntax function^
   (syntax-rules ()
     ((_ [(pattern ...) value] ...)
      (match-lambda* [(list pattern ...) value] ...))))

[1] http://www.youtube.com/watch?v=TzqYgEObfB4

Brian Mastenbrook
brian at mastenbrook.net

Posted on the users mailing list.