[racket] syntax-parse questions
On 04/12/2011 03:48 PM, Eric Tanter wrote:
> Hi,
>
> I'm starting to play with syntax-parse. Looks really great, but also quite complex.
>
> Here are some newbie questions.
> (the example is based on the defmac of Eli)
>
> I use two optional declaration:
>
> (define-syntax (defmac2 stx)
> (syntax-parse stx
> [(defmac2 (name:identifier . xs)
> (~optional (~seq #:keywords key:identifier ...))
> (~optional (~seq #:captures cap:identifier ...))
> body:expr)
> #'(define-syntax (name stx)
> (syntax-case stx (key ...)
> [(name . xs)
> (with-syntax ([cap (datum->syntax stx 'cap stx)] ...)
> (syntax body))]))])))
>
>
> 1. according to the docs, I can pass #:name in an ~optional.
> if I do so:
> (~optional (~seq #:keywords key:identifier ...) #:name "foo")
> I get:
> ~optional: unexpected keyword, expected one of (#:defaults) in: #:name
> (according to the docs there are 3 keywords for optional, name, too-many, and defaults)
There are two kinds of ~optional: one is for head patterns and the other
is for ellipsis-head patterns. The #:name keyword is only allowed in the
latter case.
> 2. my macro above works ok only if both #:keywords and #:captures are given, because if they are not, the key and cap variables get bound to #f.
> And I get messages like:
> key: attribute is bound to non-syntax value: #f in: key
>
> I therefore want to specify a default that is more reasonable than #f in my case. I looked into the #:defaults parameter of ~optional, but unsuccessfully.
> I don't know how to have it behave as I'd expect, that is, if none is given, then key ... is "zero occurrences".
Ah, sorry, the docs are incomplete for #:defaults; I'll fix that. If the
ellipsis depth is not 0 (for example, 'key' has a depth of 1), you must
specify the depth too. I think this is what you want:
(define-syntax (defmac2 stx)
(syntax-parse stx
[(defmac2 (name:identifier . xs)
(~optional (~seq #:keywords key:identifier ...)
#:defaults ([(key 1) '()]))
(~optional (~seq #:captures cap:identifier ...)
#:defaults ([(cap 1) '()]))
body:expr)
#'(define-syntax (name stx)
(syntax-case stx (key ...)
[(name . xs)
(with-syntax ([cap (datum->syntax stx 'cap stx)] ...)
(syntax body))]))]))
I wish I'd made #:defaults take patterns on the left-hand sides instead.
I'll see if I can add something like that before the upcoming release.
Hope that helps,
Ryan