www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - exceptions vs error codes

reply Superstar64 <Hexagonalstar64 gmail.com> writes:
In terms of performance and code generation exceptions are faster 
in the regular path while error codes are faster in the error 
path.

Would it be possible and a good idea to have a language feature 
that allows some exceptions to use error code code generation.
Jul 09 2016
next sibling parent reply ketmar <ketmar ketmar.no-ip.org> writes:
what i just did read?! O_O
Jul 09 2016
parent reply Seb <seb wilzba.ch> writes:
On Sunday, 10 July 2016 at 06:31:34 UTC, ketmar wrote:
 what i just did read?! O_O
Don't be drunken on the NG! If you take the time to answer, do so in a friendly and helpful way. Remember that you also started as a beginner!
Jul 09 2016
next sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
On Sunday, 10 July 2016 at 06:36:06 UTC, Seb wrote:
 Remember that you also started as a beginner!
no. i was born ideal and all-knowledgeable.
Jul 10 2016
prev sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Sunday, 10 July 2016 at 06:36:06 UTC, Seb wrote:
 On Sunday, 10 July 2016 at 06:31:34 UTC, ketmar wrote:
 what i just did read?! O_O
Don't be drunken on the NG! If you take the time to answer, do so in a friendly and helpful way. Remember that you also started as a beginner!
Well, I am sure you don't want ketmar back to where he was as a beginner... O_o
Jul 10 2016
prev sibling next sibling parent reply Jack Stouffer <jack jackstouffer.com> writes:
On Sunday, 10 July 2016 at 03:02:31 UTC, Superstar64 wrote:
 In terms of performance and code generation exceptions are 
 faster in the regular path while error codes are faster in the 
 error path.

 Would it be possible and a good idea to have a language feature 
 that allows some exceptions to use error code code generation.
If I understand correctly, you want C/Go style error codes when a function fails rather than exceptions? This is possible, it's just not used by Phobos. Just use std.variant and have your function return the value on success and the error value on failure.
Jul 09 2016
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
it seems that OP wants a kind of compiler switch (or pragma, or 
attribute) to magically turn `throw` into returning some kind of 
"error value". and we already has too much dangerous compiler 
switches like that (even one is too much, and we have two).
Jul 10 2016
parent reply Chris Wright <dhasenan gmail.com> writes:
On Sun, 10 Jul 2016 07:06:28 +0000, ketmar wrote:

 it seems that OP wants a kind of compiler switch (or pragma, or
 attribute) to magically turn `throw` into returning some kind of "error
 value". and we already has too much dangerous compiler switches like
 that (even one is too much, and we have two).
But as an annotation like nogc it would work. You do need a try/catch in every annotated function to catch runtime exceptions like OutOfMemoryError.
Jul 10 2016
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Sunday, 10 July 2016 at 16:47:31 UTC, Chris Wright wrote:
 You do need a try/catch in every annotated function to catch 
 runtime exceptions like OutOfMemoryError.
as a side note: it is even not guaranteed that one *can* catch Error. and it is plainly wrong to try to continue execution after that, as program is in undefined state.
Jul 10 2016
next sibling parent reply Chris Wright <dhasenan gmail.com> writes:
On Sun, 10 Jul 2016 16:57:49 +0000, ketmar wrote:

 On Sunday, 10 July 2016 at 16:47:31 UTC, Chris Wright wrote:
 You do need a try/catch in every annotated function to catch runtime
 exceptions like OutOfMemoryError.
as a side note: it is even not guaranteed that one *can* catch Error. and it is plainly wrong to try to continue execution after that, as program is in undefined state.
Array bounds errors, then. For associative arrays, that's a runtime method invocation. We'd have to implement every runtime method twice, or eliminate precompiled libraries, or accept that throwAsReturnValue requires every function to have a hidden try/catch.
Jul 10 2016
parent ketmar <ketmar ketmar.no-ip.org> writes:
On Sunday, 10 July 2016 at 21:31:57 UTC, Chris Wright wrote:
 On Sun, 10 Jul 2016 16:57:49 +0000, ketmar wrote:

 On Sunday, 10 July 2016 at 16:47:31 UTC, Chris Wright wrote:
 You do need a try/catch in every annotated function to catch 
 runtime exceptions like OutOfMemoryError.
as a side note: it is even not guaranteed that one *can* catch Error. and it is plainly wrong to try to continue execution after that, as program is in undefined state.
Array bounds errors, then.
any Error. spec clearly says that throwing Error doesn't guarantee proper unwinding (and by that, it may skip as many catch blocks as it want), and program is in undefined state after catching Error. in DMD, it just happened to be implemented in a way that it is possible to catch many errors, get unwinding, and such. but it isn't a requirement. and, by the way, by writing different spec-compliant implementation, one can break alot of unittests, as many unittests catching AssertError. and no, i don't know how to write a reliable and spec-compliant unittest in D with `assert`s.
Jul 11 2016
prev sibling next sibling parent reply Max Samukha <maxsamukha gmail.com> writes:
On Sunday, 10 July 2016 at 16:57:49 UTC, ketmar wrote:
 On Sunday, 10 July 2016 at 16:47:31 UTC, Chris Wright wrote:
 You do need a try/catch in every annotated function to catch 
 runtime exceptions like OutOfMemoryError.
as a side note: it is even not guaranteed that one *can* catch Error. and it is plainly wrong to try to continue execution after that, as program is in undefined state.
Undefined does not imply corrupt. There are many examples of programs that give you the last chance to save the state after a failure.
Jul 13 2016
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Wednesday, 13 July 2016 at 07:14:04 UTC, Max Samukha wrote:
 Undefined does not imply corrupt.
undefined means "undefined". there is nothing more to save, nothing more to do, as you can't rely on a single bit. this is... definition of undefined. relying on defined state with undefined behavior is not only dangerous, it is plainly invalid.
Jul 13 2016
next sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Wednesday, 13 July 2016 at 09:04:20 UTC, ketmar wrote:
 On Wednesday, 13 July 2016 at 07:14:04 UTC, Max Samukha wrote:
 Undefined does not imply corrupt.
undefined means "undefined". there is nothing more to save, nothing more to do, as you can't rely on a single bit. this is... definition of undefined. relying on defined state with undefined behavior is not only dangerous, it is plainly invalid.
Undefined by the language is not the same as unknown in a concrete instance. It simply means that such constructs are not part of the specified language.
Jul 13 2016
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Wednesday, 13 July 2016 at 09:12:56 UTC, Ola Fosheim Grøstad 
wrote:
 Undefined by the language is not the same as unknown in a 
 concrete instance. It simply means that such constructs are not 
 part of the specified language.
"program is in undefined state"? that is what written in the specs. and it means exactly that: *anything* can be messed up, including druntime internal things. the only thing one can really do here is invoke "exit" syscall as fast, as possible, or dereference zero pointer to get core dump.
Jul 13 2016
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Wednesday, 13 July 2016 at 09:53:31 UTC, ketmar wrote:
 On Wednesday, 13 July 2016 at 09:12:56 UTC, Ola Fosheim Grøstad 
 wrote:
 Undefined by the language is not the same as unknown in a 
 concrete instance. It simply means that such constructs are 
 not part of the specified language.
"program is in undefined state"? that is what written in the specs.
That is a meaningless statement. The program is never in a state. The program is the input, the source code.
 and it means exactly that: *anything* can be messed up, 
 including druntime internal things. the only thing one can 
 really do here is invoke "exit" syscall as fast, as possible, 
 or dereference zero pointer to get core dump.
That's an implementation detail.
Jul 13 2016
parent ketmar <ketmar ketmar.no-ip.org> writes:
On Wednesday, 13 July 2016 at 10:14:24 UTC, Ola Fosheim Grøstad 
wrote:
 That is a meaningless statement. The program is never in a 
 state. The program is the input, the source code.
no.
Jul 13 2016
prev sibling parent reply Max Samukha <maxsamukha gmail.com> writes:
On Wednesday, 13 July 2016 at 09:04:20 UTC, ketmar wrote:
 On Wednesday, 13 July 2016 at 07:14:04 UTC, Max Samukha wrote:
 Undefined does not imply corrupt.
undefined means "undefined". there is nothing more to save, nothing more to do, as you can't rely on a single bit. this is... definition of undefined. relying on defined state with undefined behavior is not only dangerous, it is plainly invalid.
Not true. Undefined implies there *may* be something to save. That is why programs like Steinberg Cubase do not simply bail out on failure, but give users a chance to save a copy of their work. In my experience with Cubase, state needed for recovery survived the failure more often than not.
Jul 13 2016
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Wednesday, 13 July 2016 at 10:14:41 UTC, Max Samukha wrote:
 Undefined implies there *may* be something to save.
but you have no way to know what.
 That is why programs like Steinberg Cubase do not simply bail 
 out on failure, but give users a chance to save a copy of their 
 work.
that's why they aren't portable. and written by bad programmers, as there is never any need for "emergency save" in good designed progam: it keeps working logs and can replay everything user did if it crashed. sadly, most programmers aren't trained to write their software this way.
Jul 13 2016
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Wednesday, 13 July 2016 at 10:33:52 UTC, ketmar wrote:
 On Wednesday, 13 July 2016 at 10:14:41 UTC, Max Samukha wrote:
 Undefined implies there *may* be something to save.
but you have no way to know what.
Wrong. Just because a language-spec says a compiler writer does not have to care about a particular type of input does not mean that the compiler and programmer cannot verify the data to be valid. But hey, you don't even acknowledge that there is a difference between the machine and the program, so no hope of you getting into a reasonable argument on this one. ;-)
Jul 13 2016
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Wednesday, 13 July 2016 at 11:05:32 UTC, Ola Fosheim Grøstad 
wrote:
 Wrong. Just because a language-spec says a compiler writer does 
 not have to care about a particular type of input does not mean 
 that the compiler and programmer cannot verify the data to be 
 valid.
you can't. by definition.
Jul 13 2016
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Wednesday, 13 July 2016 at 11:06:54 UTC, ketmar wrote:
 On Wednesday, 13 July 2016 at 11:05:32 UTC, Ola Fosheim Grøstad 
 wrote:
 Wrong. Just because a language-spec says a compiler writer 
 does not have to care about a particular type of input does 
 not mean that the compiler and programmer cannot verify the 
 data to be valid.
you can't. by definition.
If it is undefined, then there is no definition. Are you trolling me?
Jul 13 2016
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Wednesday, 13 July 2016 at 11:16:03 UTC, Ola Fosheim Grøstad 
wrote:
 On Wednesday, 13 July 2016 at 11:06:54 UTC, ketmar wrote:
 On Wednesday, 13 July 2016 at 11:05:32 UTC, Ola Fosheim 
 Grøstad wrote:
 Wrong. Just because a language-spec says a compiler writer 
 does not have to care about a particular type of input does 
 not mean that the compiler and programmer cannot verify the 
 data to be valid.
you can't. by definition.
If it is undefined, then there is no definition. Are you trolling me?
Please not that «undefined» does not mean «required to be arbitrary».
Jul 13 2016
prev sibling parent reply Chris Wright <dhasenan gmail.com> writes:
On Sun, 10 Jul 2016 16:57:49 +0000, ketmar wrote:

 On Sunday, 10 July 2016 at 16:47:31 UTC, Chris Wright wrote:
 You do need a try/catch in every annotated function to catch runtime
 exceptions like OutOfMemoryError.
as a side note: it is even not guaranteed that one *can* catch Error.
This is just plain wrong. The spec explicitly talks about catching Error (in the docs about TryStatement) and how to do it. I guess in the most general case, you're not guaranteed that your CPU won't catch fire in between the throw statement and the catch block? In which case we might as well throw out all programming -- and cognition, since I might get hit by a meteor while I'm pondering.
 and it is plainly wrong to try to continue execution after that, as
 program is in undefined state.
Also wrong. The spec defines the differences between Error and other Throwables. It involves how exception chaining works, if you throw an exception while handling an exception. It notably does not say that your program is in an undefined state after catching an Error. You might be saying that I could forget to clean up resources or restore invariants after an Error is thrown. But that's also true of any Throwable. Or a return statement. Again, if this sort of error bothers you so much that you refuse to write any code that could trigger it, you can't write *any* code.
Jul 13 2016
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Wednesday, 13 July 2016 at 13:13:45 UTC, Chris Wright wrote:
as Error can be thrown anywhere along the way (think, for 
example, about RangeError in expression with side-effects), and 
stack unwinding is not guaranteed (but *may* happen, and may 
happen partially), the program *is* in undefined state. that is 
why Errors aren't usual Exceptions, and that is why you should 
not assume *anything* after Error is thrown.

of course, some assumptions still can be made, but they all 
highly implementation-specific, and should be avoided in good 
code.
Jul 13 2016
parent reply Chris Wright <dhasenan gmail.com> writes:
On Wed, 13 Jul 2016 13:31:03 +0000, ketmar wrote:

 On Wednesday, 13 July 2016 at 13:13:45 UTC, Chris Wright wrote:
 as Error can be thrown anywhere along the way (think, for example, about
 RangeError in expression with side-effects), and stack unwinding is not
 guaranteed (but *may* happen, and may happen partially), the program
 *is* in undefined state. that is why Errors aren't usual Exceptions, and
 that is why you should not assume *anything* after Error is thrown.
Point to the place in the spec that it says that this is true of Error and not other Throwables.
Jul 13 2016
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Wednesday, 13 July 2016 at 13:46:44 UTC, Chris Wright wrote:
 On Wed, 13 Jul 2016 13:31:03 +0000, ketmar wrote:

 On Wednesday, 13 July 2016 at 13:13:45 UTC, Chris Wright wrote:
 as Error can be thrown anywhere along the way (think, for 
 example, about
 RangeError in expression with side-effects), and stack 
 unwinding is not
 guaranteed (but *may* happen, and may happen partially), the 
 program
 *is* in undefined state. that is why Errors aren't usual 
 Exceptions, and
 that is why you should not assume *anything* after Error is 
 thrown.
Point to the place in the spec that it says that this is true of Error and not other Throwables.
https://dlang.org/library/object/throwable.html "In principle, one should not catch Throwable objects that are not derived from Exception, as they represent unrecoverable runtime errors. Certain runtime guarantees may fail to hold when these errors are thrown, making it unsafe to continue execution after catching them."
Jul 13 2016
parent Chris Wright <dhasenan gmail.com> writes:
On Wed, 13 Jul 2016 13:50:00 +0000, ketmar wrote:
 https://dlang.org/library/object/throwable.html
 
 "In principle, one should not catch Throwable objects that are not
 derived from Exception, as they represent unrecoverable runtime errors.
 Certain runtime guarantees may fail to hold when these errors are
 thrown, making it unsafe to continue execution after catching them."
So this is two separate things coming together: 1) If the runtime is sufficiently borked, it might be unable to unwind the stack. 2) If the runtime detects that it is borked, it will throw something derived from Error. You could just as well say that *no* runtime function is guaranteed to be safe to call because the runtime could be in an invalid state without having detected it. It's merely slightly riskier when an Error has been thrown. Specific to stack unwinding, it's pretty isolated from the rest of the runtime.
Jul 13 2016
prev sibling next sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Sunday, 10 July 2016 at 03:02:31 UTC, Superstar64 wrote:
 In terms of performance and code generation exceptions are 
 faster in the regular path while error codes are faster in the 
 error path.

 Would it be possible and a good idea to have a language feature 
 that allows some exceptions to use error code code generation.
Yes, this has been discussed quite heavily in the past. It is both possible and a good idea, but it won't happen. This is quite typical for possible and good ideas around here... :-)
Jul 10 2016
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/10/2016 10:03 AM, Ola Fosheim Grøstad wrote:
 Yes, this has been discussed quite heavily in the past. It is both
 possible and a good idea, but it won't happen. This is quite typical for
 possible and good ideas around here... :-)
When has D ever done anything right in your eyes? Just curious!
Jul 10 2016
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Monday, 11 July 2016 at 04:27:35 UTC, Walter Bright wrote:
 On 7/10/2016 10:03 AM, Ola Fosheim Grøstad wrote:
 Yes, this has been discussed quite heavily in the past. It is 
 both
 possible and a good idea, but it won't happen. This is quite 
 typical for
 possible and good ideas around here... :-)
When has D ever done anything right in your eyes? Just curious!
The original plan, to redo C++ by creating a simpler formulation of the same programming model was a good plan. Inheriting many of the same problems as C++ and adding a slew of new ones was not the best move. In the case of exceptions you could've done better as you could generate meta-information that go beyond the dumb C++ manual include-file + basic linkage model. No need for D exceptions to choose the slow C++ exception handling version. You made D incompatible with C++, yet is trying too hard to make it a little bit compatible with it. I think you should make a choice, either make D fully compatible or cut all ties. Modern C++ is 80% header files and templates, linkage does not get you much compatibility these days.
Jul 10 2016
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/10/2016 10:21 PM, Ola Fosheim Grøstad wrote:
 On Monday, 11 July 2016 at 04:27:35 UTC, Walter Bright wrote:
 When has D ever done anything right in your eyes? Just curious!
[ ... more complaints about D ... ]
So what's stopping you from using Scheme?
Jul 11 2016
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Monday, 11 July 2016 at 13:20:50 UTC, Walter Bright wrote:
 On 7/10/2016 10:21 PM, Ola Fosheim Grøstad wrote:
 On Monday, 11 July 2016 at 04:27:35 UTC, Walter Bright wrote:
 When has D ever done anything right in your eyes? Just 
 curious!
[ ... more complaints about D ... ]
So what's stopping you from using Scheme?
Nothing is stopping me from using Lisp where appropriate. Why are you asking?
Jul 11 2016
prev sibling next sibling parent reply phant0m <asoeifjasoi sioudfhjsiuodhf.com> writes:
On Sunday, 10 July 2016 at 03:02:31 UTC, Superstar64 wrote:
 In terms of performance and code generation exceptions are 
 faster in the regular path while error codes are faster in the 
 error path.

 Would it be possible and a good idea to have a language feature 
 that allows some exceptions to use error code code generation.
Personally, I don't understand the need for exceptions at all. Usually, only a calling context can fix the error and continue execution of the program. If exception caught by a top level handler, all it can do is just a crash. Moreover, with exceptions, you need to wrap every piece of code with ugly "try/catch". A plain check of the return code is much better. Sometimes you can't return something adequate (when an index is out of range or container is empty). These cases are programmer's errors and assert is more than enough.
Jul 10 2016
next sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Sunday, 10 July 2016 at 17:19:31 UTC, phant0m wrote:
 Personally, I don't understand the need for exceptions at all. 
 Usually, only a calling context can fix the error and continue 
 execution of the program. If exception caught by a top level 
 handler, all it can do is just a crash. Moreover, with 
 exceptions, you need to wrap every piece of code with ugly 
 "try/catch".
No, not if you use RAII. In a web server it is quite useful to just let uncaught exceptions result in a http status and unwind transactions automatically without having to put all kinds of error checks in the core logic of the program.
Jul 10 2016
prev sibling parent Chris Wright <dhasenan gmail.com> writes:
On Sun, 10 Jul 2016 17:19:31 +0000, phant0m wrote:
 Usually,
 only a calling context can fix the error and continue execution of the
 program. If exception caught by a top level handler, all it can do is
 just a crash.
We separate execution into tasks (which could be messages in SQS, or RPCs with a REST interface, or executing a bit of AI script in a game). We observe a failure in a task. Instead of trying to do something intelligent about it inside the implementation of the task, we blindly retry the task with backoff, if appropriate. After a task has failed enough times, it's put into an error queue and the developers are notified.
 Moreover, with exceptions, you need to wrap every piece of
 code with ugly "try/catch".
Only on a code coverage level. Manual return value checking requires it on a syntactic level. That's why my Go programs are about 20% error checking -- and I *still* have to use try/catch (defer/recover, whatever, it's the same thing).
Jul 10 2016
prev sibling next sibling parent Superstar64 <Hexagonalstar64 gmail.com> writes:
On Sunday, 10 July 2016 at 03:02:31 UTC, Superstar64 wrote:
 In terms of performance and code generation exceptions are 
 faster in the regular path while error codes are faster in the 
 error path.

 Would it be possible and a good idea to have a language feature 
 that allows some exceptions to use error code code generation.
I made a DIP for this: https://forum.dlang.org/thread/gkqomdjepixcbtycvepn forum.dlang.org#post-gkqomdjepixcbtycvepn:40forum.dlang.org
Jul 10 2016
prev sibling next sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 7/9/16 11:02 PM, Superstar64 wrote:
 In terms of performance and code generation exceptions are faster in the
 regular path while error codes are faster in the error path.

 Would it be possible and a good idea to have a language feature that
 allows some exceptions to use error code code generation.
Swift does exactly this. It doesn't have exceptions, but mimics them by passing a hidden "error" parameter that is filled in if an error occurs. No stack unwinding occurs, just normal returns. This allows them to get around stack unwinding issues with ARC. I don't think this is possible for D to switch to. It would break too much code. You have to instrument your code properly to get this behavior, and it's actually quite unpleasant IMO. -Steve
Jul 11 2016
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/9/2016 8:02 PM, Superstar64 wrote:
 Would it be possible and a good idea to have a language feature that
 allows some exceptions to use error code code generation.
If you want to return an error code, return an error code. No language feature is required.
Jul 11 2016
parent reply Chris Wright <dhasenan gmail.com> writes:
On Mon, 11 Jul 2016 06:13:00 -0700, Walter Bright wrote:

 On 7/9/2016 8:02 PM, Superstar64 wrote:
 Would it be possible and a good idea to have a language feature that
 allows some exceptions to use error code code generation.
If you want to return an error code, return an error code. No language feature is required.
I think the intent is to tell the compiler: the error case is very common, so make that case faster at the expense of the happy path. Which is fine in theory, but probably not worth the effort, and it isn't really the greatest usecase for exceptions in general. If errors are so common, you probably want to impress that on the programmer with an explicit status code. For my part, I tend to follow the C# pattern of `foo` and `tryFoo`. I'm just writing a library. You can tell me whether this piece of data is trusted to be correct or not.
Jul 11 2016
parent Walter Bright <newshound2 digitalmars.com> writes:
On 7/11/2016 9:10 PM, Chris Wright wrote:
 On Mon, 11 Jul 2016 06:13:00 -0700, Walter Bright wrote:

 On 7/9/2016 8:02 PM, Superstar64 wrote:
 Would it be possible and a good idea to have a language feature that
 allows some exceptions to use error code code generation.
If you want to return an error code, return an error code. No language feature is required.
I think the intent is to tell the compiler: the error case is very common, so make that case faster at the expense of the happy path.
I really have no idea what the benefit is of telling the compiler that.
Jul 11 2016