RE: bindings
I think one question that still isn't answered to me is how a macro like this would work in a world without define-syntax
and with for-lang
:
(define (f x) x)
(define-syntax m
(syntax-parser
[(_ y) #'(f y)]))
(Both intentionally kept simple.)
If f
can't be defined in the same module as m
, it has to be "public" in some other module[1]. But worse, it means the module declaring m
has to require
the module declaring f
… for what? Not for-lang
: we don't intend to make f
a macro. But not normally, either: we don't intend to call f
in this module.[2]
And we probably don't intend to burden clients of the module defining m
with the demand that they also require a module defining f
despite never invoking f
in the source text! (Worse, would this burden mean we're back to the days of "a macro's meaning after expansion depends on the runtime environment where it was expanded"?)
The ability to make the above example work as intended is one of the properties of macro hygiene as I see it: I as macro-author control what bindings I expand to in a predictable way that can't be subverted by my clients without going through my established protocol (if any).
But this is a bit of a tangent anyway
It could be one that has a module path including
private
, our little convention for "don't poke around in here if you like stability," but that doesn't resolve other concerns. ↩︎In the existing system, you can require
f
from another module (sans phase-shifting) and then expand to a use of it, so it's not that there's a problem doing this—it's more about the ability to do something else (like keepf
private to anyone exceptrequire/expose
). I think there are some subtleties for negative phase shifts depending on how the macro is intended to be used which can get ugly, though. ↩︎