Actually, what I wrote was wrong. The key piece of information I overlooked was the following rule:
> A binding for an identifier can only capture a reference to another > if both were present in the source or introduced during a single > evaluation of a syntax or quasisyntax form, with the understanding > that the evaluation of any nested, unquoted syntax or quasisyntax > forms counts as part of the evaluation of an enclosing quasisyntax. The key phrase is “single evaluation”, so quote-syntax becomes generative: multiple evaluations of the same quote-syntax form use distinct scopes. This is interesting to me. It’s stricter than Racket’s model for hygiene, since Racket makes it legal to do things like this: (with-syntax ([def #'(define x 42)]) #'(begin def x)) ...which produces a piece of syntax that will evaluate to 42, unlike in van Tonder’s model, in which it would produce an unbound identifier error. Of course, this problem is not difficult to solve; it just requires lifting #'x into a separate binding: (with-syntax* ([id #'x] [def #'(define id 42)]) #'(begin def id)) This model... makes sense to me. I like it. It seems, on the surface, more intuitive than Racket’s model of introducing fresh scopes in the expander itself. That said, it’s still quite different from Racket’s model, so some of what I said in my last message still applies, I think. I also wouldn’t be surprised if there were some infelicities in the alternative approach I’m not immediately seeing (corner cases, perhaps?). While it’s a bit of a tangent, I’d be quite interested to finding more information on this alternate model of hygiene from anyone familiar with the tradeoffs (the SRFI that describes it does not include much in the way of comparisons). Are there strong reasons to prefer Racket’s model aside from backwards compatibility and mild convenience when procedurally assembling pieces of syntax? > On Mar 4, 2018, at 19:28, Alexis King <lexi.lam...@gmail.com> wrote: > > Sam suggested I take a look at van Tonder’s work as well on Slack, and > it’s interesting, though it isn’t what I originally had in mind. I > think it would solve the first example of mine, but it would not solve > the second. In the second example, all uses of tmp come from the same > quote-syntax form, merely multiplied via ellipsis. My first mental > model was to treat syntax classes under ellipses like distinct macro > invocations, which would require a dynamic, not lexical, treatment of > scope to be consistent with Racket’s model of hygiene. > > If I’m understanding correctly, attaching fresh scopes at quotation > rather than expansion treats the source text of the program as the > ground truth for all scoping information — if two identifiers come > from the same location in the user’s source code, they can bind each > other. This seems like a good model for most things, but it seems > radically different from Racket’s model when internal definitions are > involved, since such an interpretation would imply that this program > should produce a duplicate definition error: > > (define-syntax-rule (def-x) > (define x 42)) > > (def-x) > (def-x) > > That seems to me like an enormous break from Racket’s model of > hygiene, but it doesn’t seem wrong, just different. I could picture a > different programming language with a different macroexpander using > such a model successfully. Still, unless I’m misunderstanding the > implications here, it seems like attaching the scopes at expansion > (even if “expansion” is really “parsing with syntax classes”) rather > than quoting would be more consistent with the rest of Racket? -- 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. For more options, visit https://groups.google.com/d/optout.