[plt-scheme] I'm not saying it's a bug, but I don't understand the behavior of this code
At Wed, 15 Nov 2006 17:24:22 -0600, Kyle Smith wrote:
> However, after some more playing with it I noticed that if the same code
> were put inside a let statement, or an equivalent lambda as in this
> example, the counter stutters on the first number, repeating it twice.
> Which I suppose means that somehow it has gone through an expansion once
> without saving the state of count. This is the part I don't
> understand. See example below.
>
> (module let1 mzscheme
> ((lambda ()
> (define-syntax let1
> (let ([count 1])
> (lambda (stx)
> (define (inc!) (set! count (add1 count)))
>
> (syntax-case stx ()
> [(_ x v b)
> (begin
> (printf "expanding ~a~n" count)
> (inc!)
> (syntax (let ([x v])
> (let ([x b]) (printf "~a~n" x) x))))]))))
>
> (let1 x (let1 x (let1 x (let1 x 0 (add1 x)) (add1 x)) (add1 x))
> (add1 x))))
> )
> (require let1)
> =>
> expanding 1
> expanding 1
> expanding 2
> expanding 3
This has to do with the conversion of internal definitions into
`letrec', etc.:
* The expander for `lambda' starts expanding the body to find
definitions. As long as it finds definitions, it will collect them
to convert into a `letrec-values' or `letrec-syntaxes+values' form.
* When the expander finds a syntax definition, it executes it, just in
case the newly defined is used to generate more definition forms in
the body. So that's the first instance of the transformer for
`let1'.
* In this case, expanding the first uses of `let1' produces an
expression (not a definition), so the body of the procedure is
converted to `letrec-syntaxes+values', and then expansion continues.
* Expansion of the `letrec-syntaxes+values' form executes the
transformer expression for `let1' again. That's the second instance,
and that's where your counter starts over at 1.
* Finally, the body of the `letrec-syntaxes+values' form is expanded,
including the three remaining using of `let1'.
I think we could avoid the intermediate `letrec-syntaxes+values'
creation, and thus avoid the extra evaluation of the transformer
expression. We'll have to consider this for the next round of changes
to the expander.
Matthew