[racket] Macros: dealing with optional elements

From: Konrad Hinsen (konrad.hinsen at fastmail.net)
Date: Wed Sep 25 05:31:02 EDT 2013

Hi everyone,

I am struggling with what looks like a straightforward macro issue,
but even after reading most of the documentation three times, I am
stuck.

I want to write a macro that behaves much like struct and produces a
struct form. In particular, it should accept the struct name followed
by an optional "super" argument. Here's what I have:

   (define-syntax (foo stx)
     (syntax-parse stx
       [(_ id:id (~optional super:id) (field:id ...))
        #'(struct id super (field ...))]))

This works fine when I do give the optional argument, but not without.
I understand why, but I don't see what I can do about it. I'd need to
put something into my template that produces either "super" or
nothing.  But there doesn't seem to be any template element that can
ever produce nothing at all.

The best I could come up with is an explicit test, repeating the template
once with and once without the optional element:

   (define-syntax (foo stx)
     (syntax-parse stx
                   [(_ id:id (~optional super:id) (field:id ...))
                    (if (attribute super)
                        #'(struct id super (field ...))
                        #'(struct id (field ...)))]))

That looks way too clumsy, in particular when the template is more complicated,
as it is in my real-life application.

Can this be simplified?

Konrad.

Posted on the users mailing list.