[racket] syntax/parse ~or patterns

From: Nadeem Abdul Hamid (nadeem at acm.org)
Date: Thu Jun 9 22:18:02 EDT 2011

I'm struggling with figuring out how to work with ~or patterns and
syntax/parse. Suppose, for example, I want to write a macro that takes
any number of either single numbers or pairs of numbers. It should
expand into a list of results where each single number is negated and
each pair is summed together. Examples:

(my-macro (4 5))  ; expands to ==>  (list (+ 4 5))
(my-macro 6)      ; expands to ==> (list (- 6))
(my-macro (4 5) 6 (1 2)) ; expands to ==>  (list (+ 4 5) (- 6) (+ 1 2))

So, I start writing a syntax-parse pattern like this:

(define-syntax (my-macro stx)
  (syntax-parse stx
    [(my-macro (~or (a b) c) ...+)
     #`(list ... ???

I'm stuck on how to distinguish which situation matched in the ~or --
I've tried using 'attribute' but no matter what I do, I get problems
with either the ellipses or "pattern variables used outside of
template" or something else. I thought that something like this should
have worked:

     #`(list #,(if (attribute c) #`(- c) #`(+ a b)) ...)]))

But the ellipses are a problem. I see at the very bottom of section
8.4 in the "Syntax" library documentation
(http://docs.racket-lang.org/syntax/stxparse-specifying.html) that
there's something funky about ellipses nesting depth and ~or. So I
tried using  #, with (attribute ...) around all occurrences of c, a,
and b, and got rid of the ... and that gets me closer, but the macro
doesn't expand properly. That is, with a mess like this:

(define-syntax (my-macro stx)
  (syntax-parse stx
    [(my-macro (~or (a b) c) ...+)
     #`(list
        #,(if (attribute c)
              #`(- #,(attribute c))
              #`(+ #,(attribute a) #,(attribute b))) )]))

I get
   (my-macro (4 5) 6 (1 2))
expanding to
   (list (- (#f 6 #f)))

I kind of see what's happening, but is 'attribute' the appropriate way
to go here?

Help!

--- nadeem


Posted on the users mailing list.