Phobos 3 Discussion Notes - 02-01-2024

Sebastiaan Koppe mail at skoppe.eu
Mon Feb 5 08:55:24 UTC 2024


On Sunday, 4 February 2024 at 23:16:36 UTC, H. S. Teoh wrote:
> On Sun, Feb 04, 2024 at 09:10:20PM +0000, Sebastiaan Koppe via 
> Digitalmars-d wrote: [...]
>> I personally find exceptions useful only when I want to jump 
>> many stack frames at once.
>
> But I thought exceptions were not intended to be used in that 
> kind of way. They're more like an abort condition to 
> short-circuit the normal flow of control. If a failure 
> condition is an expected part of the program, throwing an 
> exception is probably not the best way of implementing it.

Sorry, I didn't phrase it correctly. You are right, exceptions 
obviously aren't for control flow.

I meant that I find them very useful when I'm in the bowels of a 
library and need to bubble up an error to the original caller. 
With exceptions you can do this without involving the middle 
layer; just throw and let someone else care about it.

This is very convenient. However, that is about the only thing 
that they have going for me.

>> Overall I find them taxing because they add another possible 
>> 'return' value to a function. Sometimes its documented, but 9 
>> out of 10 times you'll find out at runtime.
>
> But isn't it enough to just have a blanket catch block in the 
> dispatch code to swallow any exceptions that downstream code 
> might generate? You don't have to know exactly what it is, you 
> just catch it, abort the offending task, and move on to the 
> next one?

Sometimes that can work yes.

I find that when I'm writing server software however, I often 
want to handle a subset of the possible failures. That might 
involve a blanket retry, a retry with tweaked parameters, a 
possible fallback, etc.

Using algebraic datatypes has always been a lot more explicit for 
me.

>> Note I often write server programs. YMMV with e.g. batch 
>> programs.
>
> There are certainly valid considerations about the 
> predictability of control flow. I.e., if you call a series of 
> functions in a row and they are all nothrow, you can rest 
> assured that the control flow will reach the end of the block, 
> and not bail out on you in the middle.

Yes, exactly. I value that a lot.

> Still, when a fatal error happens deep inside some low-level 
> code and there's nothing else you can do until you get back to 
> the high-level business logic, exceptions are very useful. To 
> manually bubble the error state all the way back up the call 
> stack is just too onerous. It forces all intermediate levels of 
> code to be dependent on the exact error codes / sumtypes so 
> that it can be properly propagated up to the level where the 
> code has enough context to react to it meaningfully. This 
> increases coupling between orthogonal code. Using exceptions 
> avoids this spurious coupling.

With exceptions there is coupling as well. In fact, I would argue 
the coupling is worse since its over a wider distance. Plus you 
have to 'discover' them over time.

It is true that it can sometimes be a bit onerous. In practice 
its only in a few rare cases, so I do it and move on. The 
possible set of failures is pretty static so its not like you 
have to extend the set all the time.

---

To conclude, I guess I consider exceptions to be very 
unstructured. Not only do they rarely contain the right 
information in order to decide the next step (unless you want to 
parse strings), because it is an open hierarchy, basically 
anything goes and you have no idea what gets thrown at you.

Not to mention that a refactor might change or add an exception, 
and there is no way you get informed about that during 
compilation.


More information about the Digitalmars-d mailing list