Comparing Exceptions and Errors

Steven Schveighoffer schveiguy at gmail.com
Sun Jun 5 20:53:32 UTC 2022


On 6/5/22 8:45 AM, kdevel wrote:
> On Sunday, 5 June 2022 at 01:43:06 UTC, Steven Schveighoffer wrote:
> 
> [...]
> 
>> But you aren't perfect, and so maybe you make a mistake, and trigger 
>> an Error. The compiler handles this unexpected condition by unwinding 
>> the stack back to the main function, printing the error and exiting, 
>> so you can go fix whatever mistake you made.
> 
> For this purpose nobody needs a separate subclass named `Error`. That 
> works with `Exception`s.

You can use Exceptions instead. But the difference is they are part of 
the program instead of considered a check on the program itself.

There's a need for both.

> 
> [...]
> 
>>> If the code threw an `Exception` instead of an `Error` everything 
>>> would be fine.
>>
>> I think the point of Errors is that you can remove them for efficiency.
> 
> elephant/room.

Why? If you have a correct program, you shouldn't ever have errors 
thrown. If you do have errors thrown that's something you need to 
address ASAP.

> 
>> In other words, just like asserts or bounds checks, they are not 
>> expected to be part of the normal working program.
> 
> "removing [Errors, asserts, bounds checks] is a bit like wearing a 
> life-jacket to practice in the harbour, but then leaving the 
> life-jackets behind when your ship leaves for open ocean" [1]

It's more like leaving the floaties behind when you are doing a swim meet.

> 
> [...]
>> Consider the normal flow of a range in a foreach loop, it's:
>>
>> ```d
>> // foreach(elem; range)
>> for(auto r = range; !r.empty; r.popFront) {
>>     auto elem = r.front;
>> }
>> ```
>>
>> If both `popFront` and `front` also always call `empty` you are 
>> calling `empty` 3 times per loop, with an identical value for the 2nd 
>> and 3rd calls.
> 
> Solution: Implement explicitly unchecked popFront() and front() versions.

That's terrible. Now I have to instrument my code whenever I have a 
weird unknown error, changing all range functions to use the 
`checkedPopFront` and `checkedFront`, just to find the error. Instead of 
letting the asserts do their job.

> 
>> Having the assert allows diagnosing invalid programs without crashing 
>> your program,
> 
> That depends on the understanding of "crashing a program". If library 
> code throws an `Error` instead of an `Exception` I have to isolate that 
> code in a subprocess in order to make my program gracefully handle the 
> error condition.

You don't gracefully handle the error condition. It's like saying 
gracefully handling running into the guardrail on a road. You just 
crash, and hope you don't die. You don't just graze into it and keep 
going thinking "well, the guardrail did it's job, glad it's there, I 
plan on using it every time I go around that corner."

> 
> Think of CGI processes which provide output direct to a customer. If 
> there is an assert the customer will see the famous Internal Server 
> Error message (in case of apache httpd).

An assert triggering means, your code did something invalid. It should 
crash/exit.

Now we can have *totally separate* debates on what should be an Error 
and what should be an Exception. And not to belittle your point, I 
understand that there can be a philosophy that you *only* want 
recoverable throwables for certain code domains (I myself also have that 
feeling for e.g. out of bounds errors). It's just not what D picked as 
an error handling scheme. We have both recoverable exceptions, and non 
recoverable errors.

-Steve


More information about the Digitalmars-d-learn mailing list