[plt-scheme] Re: define-syntax by itself
On Sep 9, Blake McBride wrote:
> At 02:09 PM 9/9/2006, Eli Barzilay wrote:
> >On Sep 9, Blake McBride wrote:
> > >
> > > I probably mean something like procedural macros that allow you to
> > > specify exactly what you want without trying to do it in some higher
> > > level 4th generational descriptive pattern language. I believe
> > > there is an SRFI about this.
> >
> >Well then, `define-syntax' does just that. When you write:
> >
> > (define-syntax foo
> > (lambda (stx)
> > ...))
> >
> >you bind `foo' -- as a syntax -- to a syntax->syntax transformer
> >procedure. How you implement the procedure is up to you --
> >`syntax-rules' can construct simple transformers very easily, and
> >`syntax-case' gives you only the pattern matching part in an easy
> >way. But nothing prevents you to write your own body in the above
> >definition, and you can use the basic syntax manipulation tools
> >(syntax-e, syntax-object->datum and datum->syntax-object).
>
> This is very interesting to me. If I could deal with syntax objects
> the way I want and go back and forth between syntax objects and
> scheme objects I would be able to do anything I wanted. Once I get
> a good understanding of all this I could better understand what the
> heck is going on with syntax-case.
One thing you'll get is a headache... There are lots of details that
you avoid by using things like `syntax-case'.
> 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.
Right -- you made that expression expand to `(foo 6)', so expansion
gets stuck in an infinite loop. (But not really, see below.)
> 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
What happens here is that syntax transformers can be used as
expressions in MzScheme -- so in the above, it first uses `foo'
itself -- which is passed on to your transformer procedure.
`syntax-rules' does not allow such a case, which is why you get a
syntax error when you try to use a macro as an expression. (And you
can now see that the above infinite loop is a little different.)
> So if stx represents the "foo" token, how do you get to the 6?
(define-syntax (foo stx)
(let ([l (syntax->list stx)]) ; l will be a list or #f
(unless (and l (< 1 (length l)))
(error "boom"))
(cadr l)))
or maybe expand (foo x) => (list 'x '-> x):
(define-syntax (foo stx)
(let ([l (syntax->list stx)])
(unless (and l (< 1 (length l)))
(error "boom"))
(datum->syntax-object stx
(list #'list (list #'quote (cadr l)) (list #'quote '->) (cadr l)))))
> [...]
> I really like your suggestion. I just can't figure our how to get
> it to work at all. (I'd prefer to avoid syntax-e since it doesn't
> seem to be standard.)
The above uses `syntax->list' which is also non-standard. But none of
this is standard anyway -- if you want only standard stuff, then you
should stick to `syntax-rules' only... (Which means that you're out
of luck because there is no standard low-level macro facility in
Scheme (yet).)
--
((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay:
http://www.barzilay.org/ Maze is Life!