On Apr 27, 2016, at 2:38 PM, Matthew Butterick <m...@mbtype.com> wrote:
> I suppose I'm wondering if a) this "cooperation" among macros I'm enjoying is 
> simply a lucky side effect of both being in the same module and thus sharing 
> a 'local' environment into which the identifier is being 'introduced', and if 
> so b) there's a better way to go about this than `syntax-local-introduce`.

For future mailing-list spelunkers, this is what I was able to infer by looking 
at the scope sets of introduced identifiers and thinking about the general rule 
that applies to resolving identifiers with scope sets. 

Maybe I've got it all wrong! But I tried.

"More generally, we can define binding based on subsets: A reference’s binding 
is found as one whose set of scopes is [the largest] subset of the reference’s 
own scopes (in addition to having the same symbolic name)." (Flatt, Binding as 
Sets of Scopes)

If you want to see the scope set of an identifier, use `(hash-ref 
(syntax-debug-info id 'context))`.

SS1: Suppose "my-macros.rkt" has an ordinary `(define x ...)` . The scope set 
for that `x` looks like:

> '(#(28013923 module) #(28013924 module my-macros 0))

SS2: Suppose a macro within "my-macros.rkt" defines `x`. The scope set for that 
`x` looks like:

> '(#(1 top) #(28011205 top top4358309 0) #(28013923 module) #(28013924 module 
> my-macros 0) #(28015891 macro))

SS3: Suppose a different macro within "my-macros.rkt" defines `x`, this time 
with `syntax-local-introduce`. The scope set for that `x` looks like:

> '(#(1 top) #(28011205 top top4358309 0) #(28013923 module) #(28013924 module 
> my-macros 0))

Thus, compared to SS2, `syntax-local-introduce` has the effect of removing the 
last scope.


SS4: Now consider a macro in "my-macros.rkt" that invokes `x`. The scope set 
for that `x` looks like:

> '(#(1 top) #(28011205 top top4358309 0) #(28013923 module) #(28013924 module 
> my-macros 0) #(28015902 macro))


So if you put all these macros in one expression at the use site, what happens? 

(let ()
  ;; SS1 is the hygienic `x` hanging out back in "my-macros.rkt"
  (macro-that-defines-x) ; aka SS2
  (macro-that-defines-x-with-syntax-local-introduce) ; aka SS3
  (macro-that-invokes-x)) ; aka SS4

By the Flatt Rule of Scope Sets, the `x` in the `macro-that-invokes-x`, that 
carries scope set SS4, will resolve to a binding that has the same name & the 
largest scope subset. Both SS1 and SS3 meet these criteria. But because SS3 — 
the identifier created by `syntax-local-introduce` — has the larger subset, it 
takes precedence over SS1 (the basic hygienic `define` back in 
"my-macros.rkt"). Thus the `syntax-local-introduce` identifier overrides the 
hygienic binding.

EPILOGUE

While `syntax-local-introduce` now makes more sense to me, I still find it 
weird. Because is `syntax-local-introduce` hygienic? Well it doesn't seem 
UN-hygienic, inasmuch as it's not creating identifiers at the calling site. But 
by pruning the last scope, `syntax-local-introduce` is making an identifier 
appear as if it belongs to strange penumbral area of the macro-definition site 
that isn't otherwise accessible. Semihygienic?

More generally, it makes me wonder if scope sets themselves erode the notion of 
hygiene. Before, syntax contexts could be categorized as either being on the 
macro-definition side (hygienic) or the use side (nonhygienic), because they 
were conceptually tied to to "natural" lexical contexts in the source code.
 
So, do scope sets necessarily create a more nuanced model? As 
`syntax-local-introduce` suggests, by using set operations, you can create 
synthetic lexical contexts. Maybe manipulating those sets directly — rather 
than through proxies like `syntax-local-introduce` — could be interesting? 
Likewise adding scopes to syntax objects that have no purpose other than to 
create the possibility of matching these synthetic contexts?







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