Yes, the behavior you're seeing is a consequence of hygiene, and you should see the same behavior in other Scheme implementations.
When the expander gets to the `let-third` call, there is a `var` identifier in the macro's template that is used as a binder, and there is a `var` identifier in the macro's argument that is used as a reference. Hygiene says that a macro-introduced binder does not capture a macro-argument reference. The fact that they both originate from the *same* identifier given to `let-second-and-create-let-third` is irrelevant. The hygiene condition for `let-third` requires that they be treated differently. After all, in "ordinary" hygienic macros, the identifiers are the same also, but the fact that one is in the macro template and one is passed to the macro distinguishes them. If you want to do higher-order macro programming, the lesson is that hygienic macros are not *pure* abstractions for syntax in the same way that Racket's closures are pure abstractions for computation. That becomes a problem when you want to generate macro definitions that contain identifiers that they use as binders. Philip provided one solution (and thanks for the macro stepper plug!). The other solution is to pass `var` as an argument to `let-third`. Ryan On Wed, Sep 30, 2020 at 8:46 AM rocketnia <roki...@gmail.com> wrote: > > Hi all, > > I've been experimenting with a custom system of managed local variables, > and I came up with a hygiene test case that was failing. So then I tried > the same test case with plain Racket variables, and it failed that way > too. Here's a minimalistic example. > > Basically, this is a curried macro: The user supplies a variable and gets > a macro out, and then the user calls that macro. Can the second macro > bind the variable the user supplied to the first one? I thought it would > be able to, but this doesn't currently seem to be case on Racket v7.8 > [cs]. > > Could anyone explain what's going on with this? Is there a workaround if > I want to write this kind of macro? Should I file a bug in Racket? This > looks pretty close to R5RS Scheme, so I wonder what the situation in the > broader Scheme world is like, too. > > > #lang racket > > (require rackunit) > > (define-syntax-rule > (let-second-and-create-let-third var let-third body-of-let-second) > (let-syntax ([let-third > (syntax-rules () > [(let-third body-of-let-third) > (let ([var "third"]) > body-of-let-third)])]) > ; This binding shows that the first macro *does* manage to bind > ; the given variable, even though the second macro doesn't. > (let ([var "second"]) > body-of-let-second))) > > (check-equal? > (let ([x "first"]) > (let-second-and-create-let-third x let-third > (let-third > x))) > "third" > "Test that a macro generated by a macro can bind a variable the user > supplied to the generator macro") > > ; FAILURE > ; actual: "second" > ; expected: "third" > > > You can also find this code in Gist form here: > https://gist.github.com/rocketnia/cb83da2cfcddbf614dfe1dfc5e08792c > > Thanks in advance for any insight you have about what's going on here. > > - Nia > > -- > You received this message because you are subscribed to the Google Groups > "Racket Users" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to racket-users+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/racket-users/71daa8da-25cf-426b-b709-ee9ed25b53f0n%40googlegroups.com > <https://groups.google.com/d/msgid/racket-users/71daa8da-25cf-426b-b709-ee9ed25b53f0n%40googlegroups.com?utm_medium=email&utm_source=footer> > . > -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/CANy33qnRzmLYTLpZMEPFOabE9Hr-tk90hiaWbNcoKDZymw6kbw%40mail.gmail.com.