[racket] Getting context info from ellipses pattern vars when calling DATUM->SYNTAX
On 11/14/2010 07:52 PM, Sam Tobin-Hochstadt wrote:
> On Sat, Nov 13, 2010 at 5:09 PM, D Marshall <dmarshall207 at gmail.com> wrote:
>> I understand that DATUM->SYNTAX gets it's context
>> information from it's first argument. I have no problems
>> when using simple (non-ellipses) pattern variables, however,
>> I haven't been unable to get a strictly "ellipses pattern"
>> to work in this context (no pun intended).
> Here are two options:
>
> This is my preference - use the context of the macro application
> (define-syntax test-this
> (lambda (x)
> (syntax-case x ()
> [(_ a ...)
> (with-syntax
> ([form (datum->syntax x
> `(+ ,@(syntax->datum (syntax (a ...)))))])
> (syntax form))])))
>
> This is also common, but can break in some cases:
> (define-syntax test-this
> (lambda (x)
> (syntax-case x ()
> [(kw a ...)
> (with-syntax
> ([form (datum->syntax (syntax kw)
> `(+ ,@(syntax->datum (syntax (a ...)))))])
> (syntax form))])))
>
> The reason what you tried to do didn't work is that you need a context
> that is from the context of the macro use. The rest of the list isn't
> something the programmer originally wrote, but something that was
> generated by your macro, so it doesn't have any useful context.
This works too:
(define-syntax test-this
(lambda (x)
(syntax-case x ()
[(_ a ...)
(with-syntax
([form (datum->syntax (car (syntax->list #'(a ...)))
`(+ ,@(syntax->datum #'(a ...))))])
(syntax form))])))
(let*-values
([(one two three) (values 10 20 30)])
(test-this one two three))
> 60
I thought the reason that using #'(a ...) as the context didn't work was
because #'(a ...) creates a new syntax object by expanding `a' with the
ellipses and so you get the wrong context. But that new syntax object is
composed of objects from the original usage which is why taking the car
works.