First of all, let me say that I think lexicons look pretty cool.
Second, in Lexicons.pdf, you write the following about hygiene:
"The solution, in a nutshell, is: Within a backquote, precede any function call that you want to be non-shadowable with a comma."
I find this rather ironic considering all the ado on the forum about hygienic macros. (If this works then why did people both writing all those posts about hygiene? Not that I'm saying it doesn't...)
but if I am not mistaken you can't do the same for macros because
(mac baz args `(prs "baz:" ,@args)) ; would do this in a let if macros were first class
(mac bad args `(,baz ,@args))
gets you an error. (I've heard this could be solved with first-class macros but I have yet to see any implementation of said first class macros in arc.)
And if this is the Right Way to fix hygiene, should macro writers be expected to do this for every single macro they ever write?
Doesn't work in Arc2, but works in Anarki. Also doesn't work with macros, as you say. Macros aren't as big a deal however, because they cannot be shadowed by let or def, only by other macros with the same name.
Personally I think this is a pretty good answer to the hygiene issue. Probably not necessary in every single macro you write, but good if you intend lots of other people's code to use it.
If I understand this correctly, `(,foo ...) embeds the foo function into the s-expr returned by the macro, IOW the car of the s-expr is the function.
While I find this an interesting approach, one problem I see is that this only works as long as Arc is an interpreter. Embedding foo into the s-expr mixes up runtime values (the function foo) and expand-time values (the s-expr).
In a compiler, you would have one runtime in which foo exists, and another runtime (the expand-time, at a higher "meta level") in which the s-expr exists, and the two runtimes can never meet -- they exist on different levels of the reflective tower.
(I am not entirely sure of this, and in any case it does not apply to Lexicons.)
It turns out that the current implementation has a serious bug, so at the moment the answer is no, it doesn't. But the situation appears to be salvageable.
> If this works then why did people both writing all those posts about hygiene?
Well, this is (a form of) hygiene. But it's not complete. As others have observed, it doesn't work for macros (though once the bug is fixed it will) and you still have to put in gensyms (a.k.a. uniqs) manually to avoid downward capture.
I'm bemused that calling a function fixes in which lexical environment the functions it calls come from. Probably not something I want to use for my (emergency-shutdown) function, hmm? Or do I ensure that the functions that emergency-shutdown calls are fixed to a particular lexicon by, er, writing some other functions that call them and then calling them? But then there's the (turn-power-off) function that (emergency-shutdown) calls...
I'm not sure I quite understand this, but let me see if I can help clear up the confusion anyway.
A function, as distinct from a macro, has the property that when you call it, it will work the same way every time, even if you have provided some crazy bindings that shadow the functions it calls. For instance,