[plt-scheme] define-syntax by itself
Blake McBride skrev:
> At 04:49 PM 9/9/2006, Jens Axel Søgaard wrote:
>> Blake McBride skrev:
>>
>>> 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)))))
>
> I'm confused. In my example car of (foo 6) returns foo.
> Then its called again and I get the error when attempting
> a car on foo.
>
> You use cadr. Let's follow this through with the same logic.
> The first time you are doing a cadr on (foo 6) yielding 6.
> But, when it goes through again it should be attempting a
> cadr on the 6. That shouldn't work either.
Expanding a 6 doesn't call the transformer of foo.
Expanding a 6 simply becomes a 6.
> I think I am confused about the steps happening. In lisp
> macros it too goes through two passes. The first time
> the macro code is executed to create an s-expression.
> Then the s-expression is evaluated.
Yes. And if the s-expression is a macro call, then
the s-expression is expanded again. So define-syntax
and "lisp" behaves the same way.
> Something different is happening with define-syntax.
No.
> First of all I'm dealing with
> a syntax object instead of an s-expression in the first pass
> at least.
Yes.
> If I do (syntax-object->datum stx) do I get the s-expression
> just like the lisp macro stuff?
From the documentation:
(syntax-object->datum stx) returns an S-expression by stripping the
syntactic information from stx. Graph structure is preserved by the
conversion.
> If so, I should be able to manipulate it any way I like and then
> run datum->syntax-object on it in the end to turn it back into
> a syntax object to be evaluated.
More or less. You have to be careful not to delete any
contextual information of identifiers.
The difference between a syntax-object representing a symbol
(also known as an identifier) and a symbol is that the identifier
carries lexical information. If you simply convert it to
a symbol and then back again with (syntax-object->datum stx 'bar),
then the resulting identifier will get the lexical information
from stx. This may or may not be what you want.
Take a look at
<http://schemecookbook.org/view/Cookbook/GettingStartedMacros>
and in particular
"Writing Hygenic Macros in Scheme with Syntax-Case"
by Dybvig.
--
Jens Axel Søgaard