June 27, 2017
On Monday, 26 June 2017 at 21:53:57 UTC, John Colvin wrote:
>
> I wonder what could be done with something like this:
>
> void foo(int a)
> {
>     if (a > 0)
>         throw new BlahException("blah");
>     throw new BloopException("bloop");
> }
>
> unittest
> {
>     // NEW FEATURE HERE
>     alias Exceptions = __traits(thrownTypes, foo);
>     static assert (staticIndexOf!(BlahException, Exceptions) >= 0);
>     static assert (staticIndexOf!(BloopException, Exceptions)
> >= 0);
> }
>
> I'm imagining one could use that to do quite a lot of what checked exceptions provide.

So the only way for a programmer to know what exceptions can be thrown by a method is by running the code? In Java this is known while you are writing the code, even before you compile the code. And the compiler verifies that you are handling or passing on all possible exceptions. This is important.
June 27, 2017
On Sunday, 25 June 2017 at 17:38:14 UTC, mckoder wrote:
> I am disappointed that D doesn't have checked exceptions.

Warning, Google translate is used! (sorry)

I fully support mckoder with regard to exceptions. This is a great advantage of Java. I think, the problem with the introduction of verified exceptions in D is rather psychological, as the authors and the community mostly came from C++. Indeed, in C++, the checked exceptions failed, but I think this is more a failure of C++ than the ideas of checked exceptions. The Java experience has shown that this is a powerful tool that really helps to write reliable programs. Most of the arguments against exceptions are somewhat similar to the arguments of language lovers with a weak dynamic typing, by which listing argument types seems tedious. The relevant objection is that there is a problem with lambdas. I think everyone who started using the stream API in Java 8 was faced with this problem. But who said that you need to exactly repeat the approach of Java? When I encountered this problem, I tried to write an analog of this API, only with support for exceptions. As a result, the root of the problem was easily identified. In Java, each exception type thrown is an additional method parameter, similar to the input parameters, and there are no variadic templates for them. The correct implementation should have some TypeTuple for all the types thrown. And the possibility of calculating it. The following thoughts should be considered as speculative, I understand that these ideas will not be accepted.
Take for start the system adopted in Java. Now add 'throws auto'. This does not mean 'throws Exception'! This means that the compiler must determine what exceptions this method or function throws. Now add a default - all functions where there are no throws are treated like 'throws auto'. What does this give us? The old code without throws continues to work, since exceptions, except for intercepted ones, successfully pop up to main() and are caught by runtime. But as soon as the author began to denote throws or nothrows, he gets all the benefits of the Java exception system. In addition, if the lower layer has changed, the intermediate layers that delegate the exceptions above do not need to be rewritten, only the code that deals directly with the exception processing and declares it with throws or nothrows will be affected. (I think that you should not abuse this, libraries that are supplied as a separate product should still encapsulate the underlying exceptions in their own).

In addition, now the specification of 'throws A, B, C' lowered to 'throws ExceptionTypeTyple! (A, B, C)'. What does it give? We easily write templates that work with functions with any number of types of throws exceptions, and this can be handled according to the same rules as the other template parameters of the method.
June 27, 2017
On Monday, 26 June 2017 at 19:31:53 UTC, Moritz Maxeiner wrote:
>
> And the good *way* to achieve this result would be the following:
> - When visiting `startFoo`, the compiler automatically aggregates all different exceptions it may throw and stores the resulting set
> - If `startFoo` is going to be part of a (binary) library and its symbol is exported, also export its exception set
> - Improve the compiler's nothrow analysis such that if startFoo is called in scope S, but all of the exceptions in its exception set are caught (i.e. can't break out of scope S), it is treated as nothrow in S.
> - Enclose the call to `startFoo` in B in a nothrow scope.
 After preparing my message I read tail of the thread and see your vision very close to mine. 👍

>> So listing exceptions that can be thrown is a good thing because it helps you write more reliable code.
>
> It is a bad thing because you force a human to do a machine's job.
This is a bad necessity, but a necessary opportunity. Sometimes you need to be sure that the compiler's vision matches yours.

June 27, 2017
On Tuesday, 27 June 2017 at 00:10:32 UTC, jag wrote:
> On Monday, 26 June 2017 at 21:53:57 UTC, John Colvin wrote:
>>
>> I wonder what could be done with something like this:
>>
>> void foo(int a)
>> {
>>     if (a > 0)
>>         throw new BlahException("blah");
>>     throw new BloopException("bloop");
>> }
>>
>> unittest
>> {
>>     // NEW FEATURE HERE
>>     alias Exceptions = __traits(thrownTypes, foo);
>>     static assert (staticIndexOf!(BlahException, Exceptions)
>> >= 0);
>>     static assert (staticIndexOf!(BloopException, Exceptions)
>> >= 0);
>> }
>>
>> I'm imagining one could use that to do quite a lot of what checked exceptions provide.
>
> So the only way for a programmer to know what exceptions can be thrown by a method is by running the code? In Java this is known while you are writing the code, even before you compile the code. And the compiler verifies that you are handling or passing on all possible exceptions. This is important.

As I have pointed out, implementing such a feature for function exception sets would be *one* component; the others are mentioned here [1].

[1] http://forum.dlang.org/post/uovtkvpdagzagzhyacbp@forum.dlang.org
June 27, 2017
On Tuesday, 27 June 2017 at 00:29:53 UTC, crimaniak wrote:
> On Monday, 26 June 2017 at 19:31:53 UTC, Moritz Maxeiner wrote:
>>
>> And the good *way* to achieve this result would be the following:
>> - When visiting `startFoo`, the compiler automatically aggregates all different exceptions it may throw and stores the resulting set
>> - If `startFoo` is going to be part of a (binary) library and its symbol is exported, also export its exception set
>> - Improve the compiler's nothrow analysis such that if startFoo is called in scope S, but all of the exceptions in its exception set are caught (i.e. can't break out of scope S), it is treated as nothrow in S.
>> - Enclose the call to `startFoo` in B in a nothrow scope.
>  After preparing my message I read tail of the thread and see your vision very close to mine. 👍

I wouldn't call it a vision, since I personally don't need it.
It's just that I consider checked exceptions as an excuse for not improving a deficient compiler.

>
>>> So listing exceptions that can be thrown is a good thing because it helps you write more reliable code.
>>
>> It is a bad thing because you force a human to do a machine's job.
> This is a bad necessity, but a necessary opportunity. Sometimes you need to be sure that the compiler's vision matches yours.

I would need a concrete example that's not either solved by the steps mentioned in my post, or using compile time introspection on a function's exception set (as shown in John's idiomatic proposal [1]).

[1] http://forum.dlang.org/post/lxejskhonjtiifvvgwnd@forum.dlang.org
June 27, 2017
On Monday, 26 June 2017 at 17:44:15 UTC, Guillaume Boucher wrote:
> On Monday, 26 June 2017 at 16:52:22 UTC, Sebastien Alaiwan wrote:
>> Checked exceptions allow a lot more precision about what types of exceptions a function can throw.
>
> I totally agree that this is a problem with D right now.
This wasn't my point! I don't think there's a problem with D not having CE.
I was just pointing out the difference between "nothrow" specifications and CE.
June 27, 2017
Moritz Maxeiner <moritz@ucworks.org> wrote:
> [...]
> Or, more succinct: You must either manually write things down the
> compiler could find out in a fraction of the time via static
> analysis, or cheat the system; both cases are bad code.

It's not at all bad code to write things down that the compiler could
infer, quite the opposite.
Writing it down signals _intent_ and the compiler can check if the
implementation is matching the specification which gives you additional
security.
Additionally it allowes the compiler to do the checks locally which is much
easier.

Function signatures are interfaces which should be self-contained IMO, i.e. it should not be necessary to examine the function body. That's what signatures are for. At very least for public interfaces.

I honestly don't understand how people that care a great deal about expressive type systems can be so opposed to checked exceptions. After all they wouldn't use 'object' for everything either.

Tobi

June 27, 2017
On Monday, 26 June 2017 at 21:00:24 UTC, Guillaume Boucher wrote:
> I would say that the overload without exceptions is the "standard" one.

The C++ assumption is that exceptions are slow. So what the text you referenced says is that it provides an alternative mechanism for situations where you are testing for failure, e.g. accessing something that isn't present to see if it exists. It is a performance/convenience alternative.

Although that "nothrow design" is rather clumsy and inconvenient since you have to provide the error object yourself as a parameter.

>> It is rather clear though that C++ std lib relies heavily on exceptions.
>
> [Citation needed]

No citation needed. RAII + exceptions has been extensively described by Stroustrup as a main code structuring mechanism for C++ since the 1980s. Basic data structures like std::vector is designed with that in mind. C++ programmers that turn off exceptions also have to be careful with many areas of C++ std::lib.


June 27, 2017
On Tuesday, 27 June 2017 at 00:10:32 UTC, jag wrote:
> On Monday, 26 June 2017 at 21:53:57 UTC, John Colvin wrote:
>>
>> I wonder what could be done with something like this:
>>
>> void foo(int a)
>> {
>>     if (a > 0)
>>         throw new BlahException("blah");
>>     throw new BloopException("bloop");
>> }
>>
>> unittest
>> {
>>     // NEW FEATURE HERE
>>     alias Exceptions = __traits(thrownTypes, foo);
>>     static assert (staticIndexOf!(BlahException, Exceptions)
>> >= 0);
>>     static assert (staticIndexOf!(BloopException, Exceptions)
>> >= 0);
>> }
>>
>> I'm imagining one could use that to do quite a lot of what checked exceptions provide.
>
> So the only way for a programmer to know what exceptions can be thrown by a method is by running the code? In Java this is known while you are writing the code, even before you compile the code. And the compiler verifies that you are handling or passing on all possible exceptions. This is important.

No, that's completely the opposite of what I was suggesting. It would all be static (i.e. compile-time) introspection.
June 27, 2017
On Tuesday, 27 June 2017 at 06:10:52 UTC, Tobias Müller wrote:
>
> It's not at all bad code to write things down that the compiler could infer, quite the opposite.
> Writing it down signals _intent_ and the compiler can check if the implementation is matching the specification which gives you additional security.
> Additionally it allowes the compiler to do the checks locally which is much easier.
>
> Function signatures are interfaces which should be self-contained IMO, i.e. it should not be necessary to examine the function body. That's what signatures are for. At very least for public interfaces.
>
> I honestly don't understand how people that care a great deal about expressive type systems can be so opposed to checked exceptions. After all they wouldn't use 'object' for everything either.
>

Bravo! These are very important points!

FWIW, Bruce Eckel who is so often quoted by people who are opposed to checked exceptions comes from a dynamic language background. Here's a relevant quote by Bruce Eckel:

"I think that the belief that everything needs strong static (compile-time) checking is an illusion; it seems like it will buy you more than it actually does. But this is a hard thing to see if you are coming from a statically-typed language."

Source: https://groups.google.com/forum/#!original/comp.lang.java.advocacy/r8VPk4deYDI/qqhL8g1uvf8J

If you like dynamic languages such as Python you probably agree with Bruce Eckel. If you are a fan of static checking then I don't see how you can like that.