|
|
|
|
|
by chriswarbo
1470 days ago
|
|
> It makes it more difficult to understand during debugging how execution arrived at a certain point since the stack contains discontinuities That's a weird complaint, considering that stacks don't describe "how execution arrived at a certain point". In fact, stacks don't describe the past at all; rather, they describe the future of what's left to do (AKA the "continuation"). For example, consider this code: function foo() {
const bar = someComplexFunction();
performSomeEffect();
baz(bar);
}
If an error occurs somewhere inside `baz`, the stack trace won't mention anything about `someComplexFunction`, or `performSomeEffect`, or the vast majority of "how we arrived at" the call to `baz`. Yet it will tell us exactly what was remaining to do (namely, `baz` and `foo`).If we eliminate tail calls, stack traces are still an exact description of the continuation. The difference is that "remaining work" doesn't include a bunch of useless identity functions (i.e. redundant stack frames with no further work to do) |
|
Debugging is important. It doesn't get enough respect. Stacks are a pretty critical component of debugging, for better or worse.
It would be great if we didn't depend on this fiction quite so much. With native code, there are definitely alternative options now, such as rr[1] and Pernosco[2] where if you want to look back in time—well, you just go back in time. For JavaScript, that's becoming more and more possible with things like Replay[3]. Perhaps before long, the debugging argument will just go away.
[1] https://rr-project.org/
[2] https://pernos.co/
[3] https://www.replay.io/