On 9/7/18 7:15 PM, Tobias Mueller wrote:
On Thursday, 6 September 2018 at 14:39:12 UTC, Andrei Alexandrescu wrote:
Second, it does pay to keep abreast other languages. I had no idea (and am quite ashamed of it) that Java also has chained exceptions:

https://www.geeksforgeeks.org/chained-exceptions-java/

Now I'm surprised... is there a language (except C++) that supports exceptions that does _not_ have it?
Java: getCause()
C#: InnerException
PHP: getPrevious()
...

David Nadlinger wrote that Python also has them.

I think chained exception in D is semantically very different from other languages like Java.

In languages like Java or C# the exception chain has nothing to do with saving exceptions that are thrown in finally blocks. Instead the chain is used for a layer model. The "outer" exception is the higher level exception and the "inner" exception is the lower level cause of the higher level exception.

Often a low level exception is quite meaningless when thrown over multiple levels in the call stack. For example, imagine a program that uses a configuration file. While parsing the configuration, a misformatted number is encountered. If the NumberFormatException is propagated to the top level, it is basically useless for programmatic error handling.
This is much better:
ConfigurationException -> JsonParsingException -> NumberFormatException

The higher level exceptions are therefore directly caused by the lower level exception and always thrown _directly_ in the catch block where the lower level exception is catched and readily available. Not in a finally block and not indirectly in a function called from the catch block. Manually passing the inner exception to the constructor of the outer exception is trivial and IMO the right thing, because it's probably not always wanted.

Now in D, chained exceptions work differently.
The first exception that is thrown is deemed the "important" exception and later exceptions are simply chained to it. A direct semantic connection between the exceptions is not possible at all, since the later exception has no knowledge about the first exception at all. It also means that the order of the exceptions is reversed. The first exception is the "outer" exception which is the exact opposite of how it is meant in Java.

When handling an exception, it's not clear at all what those additional exceptions mean and how they should be handled.

Personally I find the Java/C# model much more useful.

Well indeed the upper you are on the stack, the more likely you are in a high-level function. It's a good heuristic. Sadly we cannot change chaining semantics now, but it does stand to reason to print the last exception in a chain, instead of the head, as the most relevant cause. Guess we'd do good to have such functionality in the stdlib.


Andrei


Reply via email to