At Fri, 16 May 2014 08:59:12 -0500, Robby Findler wrote: > I think I'm still missing a step here because changing the set! in > funny-set! to a reference makes the "is it an expression" sensitivity > go away (the reference works in both cases), but the explanation would > seem to still apply.
That's puzzling... > Is there something special about set!s that is > contributing here? It seems that I had made the corner smaller (and even more awkward?) with an extra check for variable references in the special case that the variable is bound in the enclosing module. I can put the same check in place for `set!`; I'm not sure that's a good idea, since it's not a general repair, but probably it's better for `set!` to be consistent with variable reference. > On Fri, May 16, 2014 at 1:47 AM, Matthew Flatt <[email protected]> wrote: > > You're running into an awkward corner of the macro system. The corner > > has to do identifiers that are produced by `generate-temporary` and > > then defined within a module. > > > > An identifier produced by `generate-temporary` doesn't claim to be from > > any particular context. If such identifier is defined within a module > > M, how do other uses of the identifier know to refer to the definition > > of M (since the identifier by itself doesn't claim to be from M)? > > > > The answer is that the definition marks the identifier as "introduced > > by a macro into M". It also marks each top-level form in a module with > > the "introduced to module M" context after expansion. The "top-level" > > modifier on "form" is crucial here. > > > > When you wrap `(funny-set! 3)` with `(void ...)`, then you delay its > > expansion until after all top-level forms are expanded. That is, > > `funny-set!` is not long a top-level form within the module. > > > > * If there's no `void`, then the `funny-set!` form is expanded, and > > the introduced variable is marked with the "introduced to M" > > context, and that matches up with the definition. > > > > * If there's a `void`, then the `(void (funny-set! 3))` form as a > > whole is marked with "introduced into M", but the `funny-set!` macro > > is not expanded, yet. Later, when `funny-set!` is expanded as a > > nested expression, then the introduced identifier is *not* marked > > with "introduced to M", and so it doesn't match up with the > > definition. > > > > I'm itching to try a new macro expander that I think would solve this > > problem, and maybe that will happen sometime this year. > > > > Meanwhile, I would write `make-funny-set` as > > > > (define-syntax (make-funny-set! stx) > > (syntax-parse stx > > [(_ v) > > (define unmarked (generate-temporary)) > > #`(begin > > (begin-for-syntax (set! funny (quote-syntax #,unmarked))) > > (define #,unmarked v))])) > > > > and also > > > > (define-syntax (funny-set! stx) > > (syntax-parse stx > > [(_ v) > > #`(set! #,funny v)])) > > > > By expanding into `begin-for-syntax`, you get the macro expander to > > help you a little more: you don't have to use `syntax-local-introduce`. > > Also, you also avoid the awkward corner, because the still-quoted > > identifier is visible to the macro expander (and therefore available > > for the "introduced to M" mark) instead of sitting in a side channel. > > > > At Thu, 15 May 2014 16:25:47 -0500, Spencer Florence wrote: > >> I'm attempting to write a macro which introduces a new id, then another > >> macro that set!s that id. > >> Example: > >> > >> #lang racket > >> (require (for-syntax syntax/parse racket/syntax)) > >> (define-for-syntax funny #f) > >> (define-syntax (make-funny-set! stx) > >> (syntax-parse stx > >> [(_ v) > >> (define unmarked (generate-temporary)) > >> (set! funny (syntax-local-introduce unmarked)) > >> #`(define #,unmarked v)])) > >> (define-syntax (funny-ref stx) > >> (syntax-parse stx > >> [(_) > >> funny])) > >> (define-syntax (funny-set! stx) > >> (syntax-parse stx > >> [(_ v) > >> #`(set! #,(syntax-local-introduce funny) v)])) > >> > >> (make-funny-set! 2) > >> (funny-set! 3) > >> (funny-ref) > >> > >> This program works as I expect, evaluating to 3. However if I change > >> (funny-set! 3) to (void (funny-set! 3)) I get the error: "set!: unbound > >> identifier in module in: g1" > >> > >> I do not get this error if I change (funny-ref) to (void (funny-ref)). > >> > >> If I look at the expansion of the (void (funny-set! 3)) program in > >> drracket's macro stepper the the g1 in (define g1 2) and the g1 in (void > >> (set! g1 3)) have the same color. > >> > >> To keep on with the strange, if I change the #,(syntax-local-introduce > >> funny) inside of funny-set! to #,funny inside the behavior of all programs > >> remains the same. > >> > >> Could someone explain whats going on? > >> > >> --Spencer > >> ____________________ > >> Racket Users list: > >> http://lists.racket-lang.org/users > > ____________________ > > Racket Users list: > > http://lists.racket-lang.org/users ____________________ Racket Users list: http://lists.racket-lang.org/users

