3 ms·
> one can dynamically modify macro expansion using the macroexpand hook That's an incredibly bad idea, and it's not dynamic except in purely interpreted Lisps
by kazinator 2y ago
> one can dynamically modify macro expansion using the macroexpand hook
That's an incredibly bad idea, and it's not dynamic except in purely interpreted Lisps that expand the same piece of code each time it is executed.
The hooks is absolutely global; whatever you put in there must not break anything.
From the spec itself: "For this reason, it is frequently best to confine its uses to debugging situations."
- pfdietz 2y agoOne would bind the macroexpand hook variable around the call to COMPILE or COMPILE-FILE for that code. The binding goes away after that. It wouldn't be global at all.
- froh 2y agoyah dynamic binding id another thing I dearly miss. thread local is like global in that it doesn't support for partial stacks of coroutines or generators. I'd love to have some dynamic _call stack based_ context lookup in languages like Python or c++.
- gpderetta 2y agoWith RAII, it is not terribly hard to build dynamic scoping on top of thread_local variables in C++. template<class T> struct scoped_replace { scoped_replace(T& ref, T new_val) : ref(ref), old_val(ref) { ref = std::move(new_val); } ~scoped_replace() { ref = std::move(old_val); } T& ref; T old_val; }; thread_local int val = 0; int foo() { return val; } int bar() { scoped_replace _(val, 42); return foo(); } int main() { foo(); // returns 0 bar(); // returns 42; foo(); // still returns 0 }
- kazinator 2y agoThat's a "shallow binding" implementation of dynamic scope which works fine enough; but if you have coroutines and continuations and such, it might not play along. Whichever thread invokes a continuation will see its own current value of the variable. Under "deep binding", where we have a dynamic environment stack, we can save that stack as part of the context of the coroutine, continuation or whatever else. It requires only one word: a pointer to the top of the dynamic environment. Whenever we restore that pointer value, we have the original environment.