Actually, that was the point I was planning to do the hack: (let ...) and friends deduce down to (fn ...) forms, so logically the place to do replacement of variable names should be in (fn ...) forms. ac-call is involved in function calling, which is really related.
However I've since changed my mind, because the problem then becomes:
(withs (do 1 re 2 mi 3)
(+ do re mi))
Bonus points if you figure out why your solution will also fail the above ^^
Because we know that macros are really just tagged procedures, we can apply them ourselves and let lexical scoping guarantee that they aren't shadowed!
Granted, it's ugly, and it only solves part of the problem, but I think it's a reasonable place to start hacking from.
>Granted, it's ugly, and it only solves part of the problem, but I think it's a reasonable place to start hacking from.
Oh, no. Because it means you'll need to (apply (rep macro) body) whenever you need to use a macro within a different macro. That's just too much bug-prone work and is completely unreasonable.
Also, on further reflection, I think perhaps the original hack is better - even given the weird behavior of (withs (do 1 re 2 mi 3) ...). If we're really making a language for quick hacking and prototyping, and giving the programmer all the tools they need, then maybe letting them redefine do is exactly the right thing to do. In your example it doesn't make sense, sure, but what if it was redefined as a function? Or a new macro that did something interesting with its body (inserted debug statements)? Maybe we should deliberately let the programmer redefine everything they want (as pg says) - and make sure not to write anything in a safer, more idiot-proof style. That's not the point of arc.
(Namespace collision is another issue. But we need a way to deal with that that only affects things when you want it to, and never when you don't.)
Oh no, heck no squared. Because if you do, that means that every macro has to publish any symbols-in-functional-position it actually creates. And every programmer has to check every macro he or she uses to make sure that any local variables he or she has do not conflict with the symbols-in-functional-position published by the macros. Hades breaking loose and all that. Funny action at a distance.
As for redefining a macro - then let's implement 'macrolet, that way we don't have capture.