Comparing Exceptions and Errors

Steven Schveighoffer schveiguy at gmail.com
Sun Jun 5 23:57:19 UTC 2022


On 6/5/22 6:09 PM, kdevel wrote:
> On Sunday, 5 June 2022 at 20:53:32 UTC, Steven Schveighoffer wrote:
> [...]
>>> 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.
> 
> I have no clue what that means.

An assert (or thrown error) is not ever supposed to happen, so it's not 
part of the program. It's a check to ensure that the program is sound 
and valid. You can feel free to insert as many asserts as you want, and 
it should not be considered part of the program.

It basically says "If this condition is false, this entire program is 
invalid, and I don't know how to continue from here."

> 
>>> [...]
>>>
>>>>> 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.
> 
> My code does not throw `Error`s. It always throws `Exception`s.

Then I guess you should just ignore Errors and let the runtime handle 
them? I'm not sure why this discussion is happening.

>>> [...]
>>>> 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,
> 
> Well, no. Just use the default. It will throw an exception if something 
> goes wrong. Of course, I must admid, if you want to compete with those 
> I-have-the-fastest-serving-http-server-guys (N.B.: HTTP not HTTPS! Did 
> anybody notice that?) reporting 50 Gigarequests per second (or so) then 
> you probably have to *measure* *the* *performance* of the 
> range/container implementation. But not earlier.

It becomes a tedious job of me to check "did I already check this? Oh I 
did, so I can call the unchecked version", and hope that a future me 
doesn't remove the original check.

Just always check, and then if you care about performance turn the 
checks off. If they are on, and it crashes the program, you need to fix 
it before turning them off. It's never a solution to just turn the 
safety checks off when they are failing to allow the program to "work".

> 
>> changing all range functions to use the `checkedPopFront` and 
>> `checkedFront`, just to find the error. Instead of letting the asserts 
>> do their job.
> 
> It is not clear to me, what you now complain about. You first criticized 
> that in
> 
> ```
> for(auto r = range; !r.empty; r.popFront) {
>     auto elem = r.front;
> }
> ```
> 
> there is triple checking that r is not empty, namely in !r.empty, in 
> r.front and in r.popFront. One check, !r.emtpy, will suffice. Hence one 
> can safely use
> 
> ```
> for(auto r = range; !r.empty; r.popFront_unchecked) {
>     auto elem = r.front_unchecked;
> }
> ```

You can do this, and then if it fails, you have to guess that maybe you 
did something wrong, and start using the checked versions.

I have encountered numerous times when I trigger these checks, and it's 
always a problem with how I wrote my code. If instead I just got a 
segfault, now I have to start digging, instrumenting, etc.

> 
> If you don't trust whomever you can simply keep the checked versions. 
> The test will then be performed thrice regardless if a test failure will 
> result in throwing an `Exception` or throwing an `Error`. AFAICS.

As the author of the range, I put the asserts in for *my* benefit, 
without affecting the user (if they so desire). I never trust the user.

If you write perfect code, turn asserts off and you won't have a 
problem, right?

If you don't write perfect code, leave them on, and you can diagnose the 
problem when it occurs instead of having to redo everything.

The thing is, I don't want there to be a battle between performance and 
correctness. This solves the issue by allowing correctness to be 
checked, without hindering the possibility of compiling with performance.

Yet, I do think D compilers don't make it easy to turn off checks in 
selected module. And as previously stated, I think some things that are 
Errors should actually be Exceptions.

-Steve


More information about the Digitalmars-d-learn mailing list