[gambit-list] Proposal for lightweight real hygienic macros in Gambit

Per Eckerdal per.eckerdal at gmail.com
Fri Mar 30 08:39:42 EDT 2012


On Wednesday 28 March 2012 at 04:08, Meng Zhang wrote:
> Looks like the only necessary primitive is something like ##namespace-resolve
> which takes an symbol as the argument and return a full current-namespace#symbol
> as the result. Then we can build the whole "alias" based system with it.
>  
>  

Well… while it is possible to do with only a ##namespace-resolve form (assuming that the namespace expansion process is indeed part of the macro expansion process and not processed strictly before or after the macros), building the system with only that would not result in a particularly smoothly functioning system. It really depends on how well you want the system to work.

To work well, all code that uses macros that use |alias| must use the auto-aliasing binding forms. Doing the auto-aliasing automatically and involuntarily, in Gambit core, would remove the requirement of all code, even code that does not directly use hygiene features, to import a special "hygiene" macro package.

Also, while the generalized (quasiquote-ish) alias could be implemented outside of Gambit core, it just seems wasteful, since it would have to reimplement much of the quasiquote machinery. Doing the same in Gambit core ought to be quite easy, because all of the functionality is already there.

I've thought some more about the requirement that all globals must have a namespace prefix, and I don't think it's strictly necessary if you have auto-aliasing. It doesn't really solve any name clash problems anyways. But if you don't have a namespace prefix on all globals, you need a way to refer to names without a prefix. An easy solution would be to have |#car| refer to the non namespace prefixed (standard) car function.

The reason that one must allow something like |#car| is that (alias car) must be able to expand do |#car|, having (alias car) expand into car would be unhygienic.

The main drawback of allowing prefix-less global names is that it requires *all* local bindings to be renamed by the auto aliasing, because you can't predict if a local binding will shadow a global one. If all globals had a namespace prefix, auto aliasing would only have to rename bindings that shadow other local bindings, which is fairly rare. This would result in prettier macroexpanded code.

The main advantage of not requiring all globals to have a namespace prefix is that it works better with the way Gambit works now, which I think is important.

To summarize: It would be possible to implement this system with only a ##namespace-resolve form, but I think this system would work best if three things were added to Gambit core:

1. The |alias| form, including the generalized quasiquote functionality.
2. Do auto-aliasing in Gambit core. Even ##let and friends should do it, there should be no way of avoiding it. Local bindings with namespace prefixes, like (let ((a#b 'a)) …) should be disallowed because it introduces unhygiene (and I can't imagine a situation where that type of unhygiene would be helpful).
3. Let symbols prefixed with only a # refer to symbols without namespace prefix, ie |#car| should be equivalent to the current system's (##let () (##namespace ("" car)) car). The fact that #car is not valid Scheme syntax (you have to write |#car|) doesn't really matter, since it would only be done indirectly through the alias form most of the time anyways.

Best,

Per Eckerdal

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.iro.umontreal.ca/pipermail/gambit-list/attachments/20120330/1493d8b4/attachment.htm>


More information about the Gambit-list mailing list