View mode: basic / threaded / horizontal-split · Log in · Help
April 03, 2013
Re: DIP33: A standard exception hierarchy
On Wednesday, 3 April 2013 at 09:20:02 UTC, Walter Bright wrote:
> On 4/2/2013 1:00 PM, Lars T. Kyllingstad wrote:
>> I definitely don't think we need an IllegalArgumentException. 
>> IMO, passing
>> illegal arguments is 1) a simple programming error, in which 
>> case it should be
>> an Error, or 2) something the programmer can not avoid, in 
>> which case it
>> requires a better description of why things went wrong than 
>> just "illegal
>> argument".  "File not found", for example.
>>
>> I didn't really consider contracts when I wrote the DIP, and 
>> of course there
>> will always be the problem of "should this be a contract or a 
>> normal input
>> check?"  The problem with contracts, though, is that they go 
>> away in release
>> mode, which is certainly not safe if that is your error 
>> handling mechanism.
>
> A bit of philosophy here:
>
> Contracts are not there to validate user input. They are only 
> there to check for logic bugs in the program itself.
>
> It's a very clear distinction, and should not be a problem.
>
> To reiterate, if a contract fails, that is a BUG in the 
> program, and the program is then considered to be in an 
> undefined state and is not recoverable.
>
> CONTRACTS ARE NOT AN ERROR HANDLING MECHANISM.

I completely agree, and this is exactly why we need 
InputArgumentError.

Lars
April 03, 2013
Re: DIP33: A standard exception hierarchy
On Wednesday, 3 April 2013 at 08:37:32 UTC, deadalnix wrote:
> On Tuesday, 2 April 2013 at 20:11:31 UTC, Lars T. Kyllingstad 
> wrote:
>> No.  To call front on an empty range is a programming error, 
>> plain and simple.  It's like trying to access the first 
>> element of an empty array.  The fact that some ranges may 
>> allow it anyway does not change anything.
>>
>
> It is illegal for a reason. For instance, with an array, it is 
> an out of bound access. I see ne benefice to hide this 
> information in a more generic RangeError. This is hiding 
> information and providing nothing more.

For arrays, RangeError is synonymous with "out of bounds".  I see 
no reason to invent a new class just for this purpose.

And note that I'm not saying that ranges should be restricted to 
*only* throwing RangeErrors.  Generally, it should be used in 
situations that are analogous to out of bounds for arrays, such 
as trying to pop past the end of the range.

However, some ranges may want to do something else in this 
situation.  An output range that writes to a file, for instance, 
may want to throw a "disk full" exception.  A wrapper range may 
simply propagate any errors from the underlying range.

RangeError is for the cases when it is not possible/necessary to 
provide more detail than "you tried to call popFront on an empty 
range, which is illegal".

Lars
April 03, 2013
Re: DIP33: A standard exception hierarchy
On Wednesday, 3 April 2013 at 08:40:52 UTC, deadalnix wrote:
> On Tuesday, 2 April 2013 at 20:11:31 UTC, Lars T. Kyllingstad 
> wrote:
>> Phobos/druntime devs can always add to the enums.  Users still 
>> have the option of subclassing if strictly necessary.
>>
>
> This is fundamentally incompatible with :
>
>> I'm not sure I agree with that rule.  And anyway, D's final 
>> switch mitigate some of the problems with classic switch.
>>
>
> As adding an entry unto the enum will break every single final 
> switch in user code.

I don't see the incompatibility.  This is exactly the purpose of 
final switch.  If the user didn't want to be forced to handle a 
new error category, they'd use normal switch instead.

You have yet to specify the problems with switch in OOP.  Maybe 
you meant something else, that final switch doesn't solve?

Lars
April 03, 2013
Re: DIP33: A standard exception hierarchy
On Wed, 03 Apr 2013 03:12:56 -0400, Lars T. Kyllingstad  
<public@kyllingen.net> wrote:

> On Wednesday, 3 April 2013 at 07:01:09 UTC, Jacob Carlborg wrote:
>> On 2013-04-02 22:15, Lars T. Kyllingstad wrote:
>>
>>> This illustrates my point nicely!  What does the shell do in this case?
>>> It treats both errors the same:  It prints an error message and returns
>>> to the command line.  It does not magically try to guess the filename,
>>> find a way to get you permission, etc.
>>
>> No, but you do know the difference. It doesn't just say "can't open  
>> file <filename>". It will say either, "file <filename> doesn't exist"  
>> or "don't have permission to access <filename>". It's a huge  
>> difference. I know _what_ went wrong with that file, not just that  
>> _something_ when wrong.
>
> Which is exactly what you'd use FilesystemException.kind and/or  
> FilesystemException.msg for.
>
> I never said there shouldn't be a way to distinguish between file  
> errors, I just said that in most cases, an entirely new exception class  
> is overkill.

Think of it this way, is there a use case where you would want to catch  
the "file not found" exception, but let the "do not have permission"  
exception go through to the next handler?  or vice versa?  This is the  
only reason to have separate classes.

Then we are in the awkward position of what to do if we need to catch  
both.  In that case, you have to have a base class that covers both.

The problem I have with this whole scheme of one class per error type is,  
you inevitably cannot cover everyone's use case, so they end up having to  
catch a base class and then doing the work to figure out what it is  
manually.

-Steve
April 03, 2013
Re: DIP33: A standard exception hierarchy
On Wednesday, 3 April 2013 at 14:11:09 UTC, Steven Schveighoffer 
wrote:

> The problem I have with this whole scheme of one class per 
> error type is, you inevitably cannot cover everyone's use case, 
> so they end up having to catch a base class and then doing the 
> work to figure out what it is manually.

Precisely.  And then, a switch over an enum is both way more 
efficient and more readable than a bunch of ifs and casts.

Lars
April 03, 2013
Re: DIP33: A standard exception hierarchy
On Wed, 03 Apr 2013 01:59:32 -0400, Lars T. Kyllingstad  
<public@kyllingen.net> wrote:

> On Wednesday, 3 April 2013 at 05:42:13 UTC, Lars T. Kyllingstad wrote:
>> The problem with assert is that it gets disabled in release mode.
>>  I think it is a bad idea to have this be the "standard" behaviour of  
>> parameter validation.
>
> Allow me to clarify my position on assert() a bit.  As a general rule, I  
> think assert() should be used to verify internal program flow and  
> program invariants, and nothing more.  Specifically, public APIs should  
> *not* change depending on whether asserts are compiled in or not.
>
> Say I am writing a function that you are using.  I don't trust you to  
> always give me correct parameters, so I check them.  (Maybe my function  
> could even do something dangerous if I didn't.)
>
>    public void myFunction(someArgs)
>    {
>        if (someArgs are invalid)
>            throw new InvalidArgumentError;
>        ...
>    }

I disagree here.  There are two "users" involved, one is the actual user,  
typing a command on the command line, and then the developer who uses the  
function.  The developer should be checked with assert, the user should be  
checked with code like you wrote.

The problem becomes apparent when developers don't check user input before  
passing to your functions.  That is on them, not you.  The library should  
be able to have all the safety checks removed to improve performance.

I wish there was a way to say "this data is unchecked" or "this data is  
checked and certified to be correct" when you call a function.  That way  
you could run the in contracts on user-specified data, even with asserts  
turned off, and avoid the checks in release code when the data has already  
proven valid.

-Steve
April 03, 2013
Re: DIP33: A standard exception hierarchy
On Wednesday, 3 April 2013 at 14:32:59 UTC, Steven Schveighoffer 
wrote:
> I wish there was a way to say "this data is unchecked" or "this 
> data is checked and certified to be correct" when you call a 
> function.  That way you could run the in contracts on 
> user-specified data, even with asserts turned off, and avoid 
> the checks in release code when the data has already proven 
> valid.
>
> -Steve

But you can. It is not much different from Range vs SortedRange, 
type systems exists exactly to solve such issues. Using UDA is 
probably even more elegant, but that is implementation details.

And it is one of big improvements both on safety and performance 
side you can get from using strongly typed languages in network 
services.
April 03, 2013
Re: DIP33: A standard exception hierarchy
On Wednesday, 3 April 2013 at 09:40:27 UTC, Lars T. Kyllingstad 
wrote:
> For arrays, RangeError is synonymous with "out of bounds".  I 
> see no reason to invent a new class just for this purpose.
>

Exactly, no need for RangeError (as out of bound access can be 
produced in many situation that don't involve ranges).

> And note that I'm not saying that ranges should be restricted 
> to *only* throwing RangeErrors.  Generally, it should be used 
> in situations that are analogous to out of bounds for arrays, 
> such as trying to pop past the end of the range.
>

The data always come from somewhere. That somewhere can't provide 
anymore data for a reason. Because you reached the end of a file 
(IOException or something) because the network disconnected 
(NetworkException) or whatever.

RangeError imply that the data magically appears from a range, 
without any actual source, which is impossible.

> However, some ranges may want to do something else in this 
> situation.  An output range that writes to a file, for 
> instance, may want to throw a "disk full" exception.  A wrapper 
> range may simply propagate any errors from the underlying range.
>

Exactly. In general, wrapper should simply forward calls and let 
the source fail when its own logic isn't involved.

> RangeError is for the cases when it is not possible/necessary 
> to provide more detail than "you tried to call popFront on an 
> empty range, which is illegal".
>

It is always illegal for a reason.
April 03, 2013
Re: DIP33: A standard exception hierarchy
On Wednesday, 3 April 2013 at 14:32:59 UTC, Steven Schveighoffer 
wrote:
> On Wed, 03 Apr 2013 01:59:32 -0400, Lars T. Kyllingstad 
> <public@kyllingen.net> wrote:
>>
>> Say I am writing a function that you are using.  I don't trust 
>> you to always give me correct parameters, so I check them.  
>> (Maybe my function could even do something dangerous if I 
>> didn't.)
>>
>>   public void myFunction(someArgs)
>>   {
>>       if (someArgs are invalid)
>>           throw new InvalidArgumentError;
>>       ...
>>   }
>
> I disagree here.  There are two "users" involved, one is the 
> actual user, typing a command on the command line, and then the 
> developer who uses the function.  The developer should be 
> checked with assert, the user should be checked with code like 
> you wrote.
>
> The problem becomes apparent when developers don't check user 
> input before passing to your functions.  That is on them, not 
> you.  The library should be able to have all the safety checks 
> removed to improve performance.

Some, yes, but not all.  You always have to weigh the benefit, 
i.e. the improved performance, against the drawbacks, i.e. 
reduced safety.  If you are removing trivial safety checks from a 
function that performs a very expensive and possibly dangerous 
operation -- a disk operation, say -- you're doing something 
wrong.

I agree it should be possible to remove safety checks from 
functions which are expected to be performant, and where the 
checks will have an impact (e.g. the range primitives), but it 
should be done with a less attractive compiler switch than 
-release.

I think it's a big mistake to encourage programmers to ship their 
programs with array bounds checks and the like disabled.  Such 
programs should be the exception, not the rule.  It's always 
better to err on the side of safety rather than performance.


> I wish there was a way to say "this data is unchecked" or "this 
> data is checked and certified to be correct" when you call a 
> function.  That way you could run the in contracts on 
> user-specified data, even with asserts turned off, and avoid 
> the checks in release code when the data has already proven 
> valid.

That would be awesome indeed.

Lars
April 03, 2013
Re: DIP33: A standard exception hierarchy
On Wednesday, 3 April 2013 at 09:44:23 UTC, Lars T. Kyllingstad 
wrote:
> I don't see the incompatibility.  This is exactly the purpose 
> of final switch.  If the user didn't want to be forced to 
> handle a new error category, they'd use normal switch instead.
>

This is a good thing in your own code. But in phobos, this is a 
guarantee to break a lot of user code when adding to the enum.

> You have yet to specify the problems with switch in OOP.  Maybe 
> you meant something else, that final switch doesn't solve?
>

The idiomatic way to execute code depending on a value in OOP is 
virtual dispatch.
6 7 8 9 10 11 12 13 14
Top | Discussion index | About this forum | D home