Thank you to both of you for your detailed responses! I think this is
all fascinating.

> On Mar 5, 2018, at 05:18, Ryan Culpepper <ry...@ccs.neu.edu> wrote:
> 
> 1. Yes. To me, at least :) That aspect of hygiene is triggered by a
> macro expansion step, and the macro expansion step also defines the
> boundary of its effect. In other words, the expansion of a macro
> introduces a scope, but syntax classes do not. Compare with the
> following examples:

Yes, this is what I meant when I wrote that “Syntax classes behave like
phase 1 functions, not macros.” It is worth pointing out, however, that
not all things that behave like macros are strictly within the realm of
the macroexpander — things like match expanders and syntax/parse pattern
expanders manually emulate hygienic expansion despite not ever actually
yielding to “the” macroexpander.

> 2. I think the main technical challenge is finding all of the syntax
> objects to flip the scope on, given that syntax classes allow
> attributes to have arbitrary values (like opaque structures and
> closures), not just syntax objects. We have a similar problem with
> syntax properties, which are invisible to the hygiene algorithm.
> 
> It might be easier in a macro system like Andre van Tonder's system,
> as Matthew and Sam mentioned.

The parallel with syntax properties is a good one, and it’s something
that came to mind to me, too. It seems hard to solve in general
automatically, but some cooperation from the user might be enough (via
some generic protocol like structure type properties). That’s a bit
ugly, though.

> 3. Maybe. Half-baked musings follow:

If these are your half-baked musings, I would like to see what your
fully baked ones look like. :)

Your points are good ones, and I agree that I have virtually no
intuition for which places the boundaries make sense. I will say this,
however: while I have developed over the years a reasonably strong
intuition for how Racket macros operate, when I was learning the macro
system for the first time, I did not find some parts of the hygiene
algorithm terribly intuitive. The fact that quoted syntax could be in
wildly different lexical contexts but capture and bind the same
identifiers because they were in the same dynamic context seemed
antithetical to hygiene to me (which I heard described as “respecting
the lexical structure of the program as-written”).

I find André van Tonder’s system compelling, but I also agree I can’t
really evaluate it without trying to write some programs with it. Maybe,
with Racket 7, it’d be easier to implement such a macro system in a fork
of Racket for experimentation... but the result might be too
incompatible with existing code to serve any purpose. It would be an
interesting experiment.

> On Mar 5, 2018, at 06:45, Matthew Flatt <mfl...@cs.utah.edu> wrote:
> 
> Adding to Ryan's answer, I note that Andre van Tonder's SRFI-72 system
> has `quasisyntax` is a primitive. That is,
> 
>  #`(x #,y x)
> 
> is not like
> 
> (datum->syntax #'here (list #'x y #'x))
> 
> because the scope introduced by a `quasisyntax` spans the whole
> `quasisyntax` form and causes nested `syntax` forms to not introduce
> a fresh scope.

Yes, I noticed that, too. My assumption was that a form like
with-fresh-renaming-scope would be necessary, but it would be a little
bit different from the version originally described. Rather than require
it in order to produce distinct scopes from distinct uses of quotation,
keep the behavior of the final version of SRFI 72, but allow
with-fresh-renaming-scope (or, most likely, something similar but with
a more appropriate name) to *weaken*, not strengthen, the hygiene rules.

To illustrate, this would lead to the following behavior:

    (bound-identifier=? #'x #'x) ; ==> #f

    (with-fresh-renaming-scope
      (bound-identifier=? #'x #'x)) ; ==> #t

If uses of with-fresh-renaming-scope are nested, the outermost use
“wins”, yielding the following behavior:

    (with-fresh-renaming-scope
      (bound-identifier=? (with-fresh-renaming-scope #'x)
                          (with-fresh-renaming-scope #'x)))
    ; ==> #t

This would allow forms like quasisyntax to introduce
with-fresh-renaming-scope in their expansions to avoid distinct uses of
syntax from generating distinct identifiers while simultaneously
allowing new abstractions to be defined in terms of quasisyntax just as
quasisyntax is defined in terms of syntax.

Some parts of this are still a little unsatisfying, however. The draft
of SRFI 72 you link defines with-fresh-renaming-scope as applying
lexically, not dynamically, but it isn’t immediately obvious to me which
is the correct behavior in this case. Furthermore, if it applies
lexically, what does it mean when with-fresh-renaming-scope is
introduced by a macro? If it applies to all identifiers inside its
expansion, that feels unhygienic enough to cause trouble... so my own
intuition here is nonexistent.

As for looking at the discussion, it doesn’t appear to be particularly
illustrative. As far as the archives indicate, André himself made the
change unprompted, so it’s possible there were some off-list
conversations that led to the decision, or he just changed his mind. The
only explanation given is “A rationale based on referential transparency
is given that this is the right choice.”

Anyway, this has all been quite interesting. I’ll think about it, and
maybe I’ll play around with an implementation if I get some spare
time... though I am running the risk once again of having too many
projects and never getting anything done on any of them, so we’ll see.
:)

Alexis

-- 
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.

Reply via email to