3 ms·
Hi Andy, it's been a long time since I pestered you. Glad to see Zig coming along so well. Congratulations on the progress! I'll apologize in advance for the lo
by caspper69 2y ago
Hi Andy, it's been a long time since I pestered you. Glad to see Zig coming along so well. Congratulations on the progress! I'll apologize in advance for the long post.
Wrt exceptions, you didn't elaborate. Exception handling can be a hot button issue with passionate opinions. My comments are general in nature; they are not specifically directed toward you or the Zig language.
IMHO, exception handling is inherently neither good nor bad- it is merely a mechanism; it has upsides and downsides, and the context in which they are being discussed / analyzed / used should be the guiding factor.
C provides no bounds or overflow checking. In the context of a system which must not fail, you are then forced to use some combination of rigorous assertions, overflow flag checking, and return value verification. It's cumbersome and ugly.
Rust provides both bounds checking and overflow checks (in debug mode at least). Asserts are still available, but are not required in as many instances as in C.
Neither of those languages provide what we would consider to be exceptions or exception handling. An argument could be made that if you squint the right way that Rust's resume after panic is a form of exception handling, but that's a semantic debate, and it would certainly be considered non-traditional if it were to be categorized as such. Wrt C, it had never occurred to me that setjmp()/longjmp() could be used as an exception handling mechanism. I have always seen them used as a context-switching mechanism for e.g. tasking (green-threads).
In languages that provide exception handling, both runtime and user defined exception conditions are handled by the runtime itself (oftentimes behind the scenes). This mechanism allows one to provide a catch-all lexical scope for handling exceptions, which can be cleaner and more ergonomic from a programmer perspective and can be simpler to reason about (although this is certainly debatable). It also provides an opportunity to handle conditions that might be unknown or unforeseen at the time the code is being written. Defer semantics in a language without exceptions might be considered a mid-ground approach.
The usual complaints with exceptions are: (1) that they essentially constitute hidden control flow and hidden code execution that happens outside of the plain reading of the source; (2) that you pay the performance penalty for checking / verifying the exception conditions at every line of code (also see #1); (3) that the conditions considered "exceptional" by most implementations are instead just run-of-the-mill error conditions that should be handled explicitly; and (4) that there is no well-defined structure or convention for where and when to handle exceptions and when to pass them up the stack (again, see #1) which results in a spaghettification of sorts.
C++ (optional), Java, JS, Python and C# (among many others) all provide exception handling and are all mainstream.
My general rule of thumb (which is always subject to situational variance) is that application code benefits from robust exception handling while systems level or performance critical code should not use exceptions, or at a minimum should be very judicious with usage.
Exceptions can be abused and misused like any other feature, but the reduction in repetitive manual error checking (see Go) can be a win for many teams.
YMMV of course- we have all been dragged into the 7th circle of hell at one time or another, and programming features are a lot like liquor; once you've gotten sick on one, it's near impossible to go back.