[racket] match-loop

From: William James (w_a_x_man at yahoo.com)
Date: Wed May 16 21:55:28 EDT 2012

Another looping macro.

(define-syntax-rule (do-match-loop
    (sym ...) (pat ...) (lst ...) (expr ...))
  (let loop ((sym lst) ...)
    (when (andmap cons? (list sym ...))
      (match-let ((pat sym) ...)
        (call-with-values (lambda () expr ...) loop)))))

(define-syntax match-loop-aux
  (syntax-rules ()
    [(_ () (sym ...) pats lsts form)
     (do-match-loop (sym ...) pats lsts form)]
    [(_ (x x* ...) (sym ...) pats lsts form)
     (match-loop-aux (x* ...) (tmp sym ...) pats lsts form)]))

(define-syntax-rule (match-loop (pat lst) ... form)
  (match-loop-aux (pat ...) () (pat ...) (lst ...) form))


;; Testing:

(match-loop
  ((list a a* ...) '(2 3 4))
  ((displayln a)
   a*))

2
3
4


;; Early exit
(match-loop
  ((list a a* ...) '(3 5 8))
  ((if (odd? a)
     (begin (displayln a)
            a*)
     null)))

3
5


;; Destructuring
(match-loop
  (`((,a ,b) ,more ...) '((2 3) (8 9)))
  ((printf "~A -- ~A\n" a b)
   more))

2 -- 3
8 -- 9


;; Parallel
(match-loop
  ((list a a* ...) '(5 6 7))
  ((list b b* ...) '(m n o))
  ((displayln (list a b))
   (values a* b*)))

(5 m)
(6 n)
(7 o)


;; Parallel, criss-crossing
(match-loop
  ((list a a* ...) '(5 6 7 8))
  ((list b b* ...) '(m n o p))
  ((displayln (list a b))
   (values b* a*)))

(5 m)
(n 6)
(7 o)
(p 8)


;; Move through list 2 items at a time
(match-loop
  ((list p v more ...) '(e 3 f 6 g 9))
  ((printf "~A ~A\n" p v)
   more))

e 3
f 6
g 9


;; Nested loops
(match-loop
  ((list a a* ...) '(2 3 4))
  ((match-loop
     ((list b b* ...) '(x y))
     ((printf "~a ~a\n" a b)
      b*))
   a*))

2 x
2 y
3 x
3 y
4 x
4 y



Posted on the users mailing list.