Skip to content

IfYoureNotConfusedYoureNotPayingAttention

Ben Christel edited this page Aug 11, 2021 · 2 revisions

Here is an explanation of how exceptions work, from Eloquent JavaScript.

Exceptions are a mechanism that makes it possible for code that runs into a problem to raise (or throw) an exception. An exception can be any value. Raising one somewhat resembles a super-charged return from a function: it jumps out of not just the current function but also its callers, all the way down to the first call that started the current execution. This is called unwinding the stack. You may remember the stack of function calls that was mentioned in Chapter 3. An exception zooms down this stack, throwing away all the call contexts it encounters.

If exceptions always zoomed right down to the bottom of the stack, they would not be of much use. They’d just provide a novel way to blow up your program. Their power lies in the fact that you can set “obstacles” along the stack to catch the exception as it is zooming down. Once you’ve caught an exception, you can do something with it to address the problem and then continue to run the program.

The first thing that struck me when I read this was that the author, Marijn Haverbeke, apparently thinks about the call stack using a spatial metaphor that's the opposite of mine. In my world, one function calls another and the stack grows down. That means exceptions go up. In his world, main is at the bottom, and the stack grows up. Nothing wrong with that—it is the most natural way to map the idea of a physical stack of things into the abstract space occupied by computational processes. But it has repercussions.

For one thing, it's now slightly more confusing to say that we "raise" an exception. We raise it and it goes down? Yes, you can think of this like "raising a flag" or "raising an objection", and indeed that's probably the sense in which "raise an exception" is meant. but now we have two metaphors.

The second, more serious problem is that the call stack and the dependency hierarchy (assuming we're writing procedural code) now go in opposite directions. If A calls B and we navigate from A to B when looking at our source code, we're going down the dependency hierarchy. But when the program runs, suddenly this is reversed—to go from A to B we go up the stack.

This kind of thing probably doesn't pose a problem for experts. But I imagine it's incredibly frustrating for novices, who expect that "up" and "down" refer to different things, and naturally assume that if the expert starts saying down when the novice expected to hear up, then it's they, the novice, who are missing something. To make matters worse, different experts use different conventions. JavaScript prints exception stacktraces with the most recent call first—at the top. But Ruby and Python do the opposite.

I think it's important to remember, when learning to program or just learning some new thing in programming, that this confusion does not mean you're stupid. On the contrary, it means you're smart enough to detect contradictions! If you're not confused, you're not paying attention.

Clone this wiki locally