[plt-scheme] define-syntax by itself
Blake McBride skrev:
> I'd like to play with this. I did try for a few minutes and couldn't get
> anywhere. For starters, on entry stx, I presume, is a syntax object
> representing my call. I presume the lambda must also return a syntax
> object.
> Since stx is already a syntax object I tried:
>
> (define-syntax foo
> (lambda (stx)
> stx))
>
> (foo 6)
>
> and the system hangs.
The expansion of (foo 6) calls the transformer
associated with foo namely (lambda (stx) stx)
with the syntax-object #'(foo 6). Since the
transformer is the identity the result is #'(foo 6).
Now this needs to be expanded. And you have an
infinite loop.
> If I try:
>
>
> (define-syntax foo
> (lambda (stx)
> (syntax-object->datum stx)))
>
> (foo 6)
>
> I get: foo: return value from syntax expander was not syntax: (foo 6)
A transformer must return a syntax-object as a result.
> If I try:
>
> (define-syntax foo
> (lambda (stx)
> (datum->syntax-object stx (car (syntax-object->datum stx)))))
>
> (foo 6)
>
> I get: car: expects argument of type <pair>; given foo
>
> So if stx represents the "foo" token, how do you get to the 6?
You missed that the transformer is called twice.
To expand (foo 6) the transformer is called with the syntax-object
#'(foo 6).
The (car (syntax-object->datum stx)) extract the symbol foo,
and the (datum->syntax-object stx ...) converts it to an identifier
that are returned as the result.
Now the result is expanded. Now the transformer is called with
the single identifier #'foo. The (syntax-object->datum stx)
converts it to the symbol 'foo. And now (car 'foo) gives
the error you see.
To get the 6 take the cadr instead of the car.
(define-syntax foo
(lambda (stx)
(datum->syntax-object stx
(cadr (syntax-object->datum stx)))))
> Of course if I try:
>
>
> (define-syntax foo
> (lambda (stx)
> (datum->syntax-object stx (syntax-object->datum stx))))
>
> (foo 6)
>
> I get the system hang again (I'm now full loop).
Almost the same reason as before. Can you see why?
--
Jens Axel Søgaard