[racket] Pattern matching define macro

From: Brian Adkins (racketusers at lojic.com)
Date: Sat Jul 12 12:53:52 EDT 2014

I'm porting more Haskell code to Racket as a learning exercise. When I got to this line:

isPos (r,c) = elem r [0..4] && elem c [0..r]

I first wrote this:

(define (is-pos r c) (and (member r (lgen 0 4))
                          (member c (lgen 0 r))))

where lgen is:

(define (lgen m n) (build-list (+ 1 (- n m)) (λ (x) (+ x m))))

I think (lgen 0 r) is a reasonable alternative to [0..r], and the minor additional length of the Racket version is fine.

I then decided that I may prefer to a list of row/col instead of individual args and bumped into a need for destructuring a list, so I wrote this macro:

(define-syntax defpat
  (syntax-rules ()
    [(_ (fn pat) b1 b2 ...)
     (define fn (match-lambda [pat b1 b2 ...]))]))

which allows:

(defpat (is-pos (list r c)) (and (member r (lgen 0 4))
                                 (member c (lgen 0 r))))

The fact that this is such a common operation and I couldn't find anything built-in makes me think that I may be missing something. Is this a reasonable solution? Are there better alternatives?

I suppose a better name might be in order since it's not matching one of several patterns; in this case, it's really just for destructuring a list more concisely.

I'm still blown away by how easy it was to mold Racket closer to what I wanted. I've just barely begun learning macros, but syntax-rules made this pretty easy. 

I think the only thing that sticks out is the "list" function, but that seems like a reasonable sacrifice given the flexibility it allows for in more complicated patterns.

Thanks,
Brian

--
Brian Adkins
Lojic Technologies, LLC
http://lojic.com/



Posted on the users mailing list.