February 24, 2022

On Thursday, 24 February 2022 at 00:51:31 UTC, Alexandru Ermicioi wrote:

>

Go is a no go, due to constant if else error checking it forces user to do.

Personally I actually kind of prefer how Go handles things. I know people absolutely love to shit on the if err != nil spam, but to me it makes control flow really simple to follow.

I think if we were to have value-type exceptions in D, the most important thing would be syntax.

Some very not thought out and wacky ideas to try and spark someone else to make an actually good idea:

// Running a series of functions, and only caring if they returned an exception afterwards
// (this particular syntax would obviously introduce ambiguous syntax if used, but it's an example)

alias ConvException = ValueException!"conv";

// In this example, functions can only return a single type of exception
int toInt(string str) throw(ConvException)
{
   if(isNumber(str))
      return toNumber(str);
   throw typeof(throw)("str is not a number");
}

int a;
int b;

// Even if an exception is thrown, things are still ran until the end
// only then are the catch statements ran.
try(ConvException ex) {
   a = toInt("123") catch(ex);
   b = (toInt("345") catch(ex) + toInt("abc") catch(ex));
}
catch(ConvException ex)
{
    writeln(ex.msg);
    return -1;
}

On a similar vein, if we have that sort of catch expression shown above, we could possibly make our own version of if err != nil spam look even worse :D!

ConvException ex;

if(toInt("123") catch(ex) + toInt("abc") catch(ex) && ex.isError)
{
    writeln(ex.msg);
    return -1;
}

On the topic of function chaining, let me introduce you to this beauty that my head just came up with.

Exception1 a;
Exception2 b;
Exception3 c;

// "@a" means "capture any exception into `a` and go straight to the catch block if something was thrown.

try someValue.func1()@a.func2()@b.func3@c
catch(a){}
catch(b){}
catch(c){}

(Don't ever let me design my own language).

But the point is, if we want to avoid Go's if-else spam, we need some other weird syntax to sugar on top of things.

February 24, 2022

On Thursday, 24 February 2022 at 03:42:42 UTC, SealabJaster wrote:

>

// (this particular syntax would obviously introduce ambiguous syntax if used, but it's an example)

Whoops, meant to remove that part. The original version of that example was even more amazing/ridiculous :D

February 23, 2022
On 2/23/2022 4:19 PM, meta wrote:
> I moved away from them completly in C++, i wish i could do the same with D..

dmd does not use exceptions at all.

One of the requirements I proposed for Phobos2 was for it to not use exceptions.
February 24, 2022
After having built a result library on top of std.sumtype, and used it in some small programs, I have more appreciation for exceptions as its interface for error handling effects less clutter. And D's implementation could even be improved as shown by Adam's efforts and posts in this very thread. (Quite fond of rikki's ideas.)
February 24, 2022
On 24/02/2022 1:34 PM, meta wrote:
> If the fundamentals of the feature are to be rethought / redesigned because considered harmful (performance penalty is harmful, at least to me), then the users must be prepared and educated, so they understand the motive of a potential change, and can design APIs with that in mind!

I am not proposing that we remove or modify runtime exceptions that we currently have. They serve a purpose even if I don't use them.

It can be reimplemented under the hood, but this is something that no user should ever notice. So there isn't any education required unless you want to throw them pretty much.
February 24, 2022
On 24/02/2022 6:05 PM, Walter Bright wrote:
> One of the requirements I proposed for Phobos2 was for it to not use exceptions.

This is the sort of code we are going to end up with without a solution like value type exceptions. Explicit error types and returns ala @mustuse are not better than runtime exceptions, they are much worse for readability.

We need a better solution than this.

            if (isF || isLF) {
                auto destinationr = destination.get!float("r"), destinationg = destination.get!float("g"),
                    destinationb = destination.get!float("b");
                assert(destinationr, destinationr.error.toString());
                assert(destinationg, destinationg.error.toString());
                assert(destinationb, destinationb.error.toString());

                destinationr = sourceR;
                destinationg = sourceG;
                destinationb = sourceB;
            } else if (isI8 || isLI8) {
                auto destinationr = destination.get!ubyte("r"), destinationg = destination.get!ubyte("g"),
                    destinationb = destination.get!ubyte("b");
                assert(destinationr, destinationr.error.toString());
                assert(destinationg, destinationg.error.toString());
                assert(destinationb, destinationb.error.toString());

                destinationr = cast(ubyte)(sourceR * 255f);
                destinationg = cast(ubyte)(sourceG * 255f);
                destinationb = cast(ubyte)(sourceB * 255f);
            } else if (isI16 || isLI16) {
                auto destinationr = destination.get!ushort("r"), destinationg = destination.get!ushort("g"),
                    destinationb = destination.get!ushort("b");
                assert(destinationr, destinationr.error.toString());
                assert(destinationg, destinationg.error.toString());
                assert(destinationb, destinationb.error.toString());

                destinationr = cast(ushort)(sourceR * 65535f);
                destinationg = cast(ushort)(sourceG * 65535f);
                destinationb = cast(ushort)(sourceB * 65535f);
            } else
                assert(0);
February 24, 2022
On Thursday, 24 February 2022 at 05:05:27 UTC, Walter Bright wrote:
> On 2/23/2022 4:19 PM, meta wrote:
>> I moved away from them completly in C++, i wish i could do the same with D..
>
> dmd does not use exceptions at all.
>
> One of the requirements I proposed for Phobos2 was for it to not use exceptions.

Well, now it's me that is 'confused'.

That is, how do I reconcile your above statement with your previous statement:

"Why exceptions for error handling is so important" - Walter Bright.

https://forum.dlang.org/post/m8tkfm$ret$1@digitalmars.com


February 24, 2022
On Wednesday, 23 February 2022 at 18:27:45 UTC, deadalnix wrote:
> On Wednesday, 23 February 2022 at 14:26:41 UTC, matheus wrote:
>> Just saw this today:
>>
>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2544r0.html
>>
>> Seems relevant to any System Language like D that features Exceptions.
>>
>> Matheus.
>
> This is an interesting paper, but I'm not sure where they are going with it.
>
> Exception are expensive. They need to be used to handle unexpected things. That's kind of in the name. Things that happen often are not exceptional.
>
> Pretty much all workaround they look at incur some performance penalty on the happy path, but this is not a bug, this is a feature. Exceptions are very cheap when not thrown, very expensive when thrown. This is what you want when handling a situation that is exceptional.
>
> The perf they measure for std::expect would be worth investigating. Why is it slow?

They aren't going anywhere, most of Herb's latest papers seem like ideas how the language could be improved upon, but beyond the original paper, presentation at CppCon and eventually some prototype available on Compiler Explorer, little more has happened.

I might be wrong here, but from C++ mailings it is clear nothing is happening with those papers.

Also in regards to exceptions, Bjarne has a paper where he criticizes the current compiler implementations for leaving performance improvements on the table by not wanting to break existing ABIs, while arguing against Herb's approach.

"C++ exceptions and alternatives"

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1947r0.pdf
February 24, 2022
On Thursday, 24 February 2022 at 07:23:34 UTC, rikki cattermole wrote:
>
> On 24/02/2022 6:05 PM, Walter Bright wrote:
>> One of the requirements I proposed for Phobos2 was for it to not use exceptions.
>
> This is the sort of code we are going to end up with without a solution like value type exceptions. Explicit error types and returns ala @mustuse are not better than runtime exceptions, they are much worse for readability.
>
> We need a better solution than this.

So why not have this implemented as underlying mechanism for existing try catch syntax, with option to choose which one to use?

If done so, there shouldn't be any usability downgrade, when selecting either existing or new exception mechanism, only distribution of performance overhead will change.


February 24, 2022

On Thursday, 24 February 2022 at 03:42:42 UTC, SealabJaster wrote:

>

On Thursday, 24 February 2022 at 00:51:31 UTC, Alexandru Ermicioi wrote:

>

Go is a no go, due to constant if else error checking it forces user to do.

Personally I actually kind of prefer how Go handles things. I know people absolutely love to shit on the if err != nil spam, but to me it makes control flow really simple to follow.

It may be simpler, but it is also way noisier than try catch & throw, and way more easier to trip over it and have a bug.

>

I think if we were to have value-type exceptions in D, the most important thing would be syntax.

Some very not thought out and wacky ideas to try and spark someone else to make an actually good idea:

// Running a series of functions, and only caring if they returned an exception afterwards
// (this particular syntax would obviously introduce ambiguous syntax if used, but it's an example)

alias ConvException = ValueException!"conv";

// In this example, functions can only return a single type of exception
int toInt(string str) throw(ConvException)
{
   if(isNumber(str))
      return toNumber(str);
   throw typeof(throw)("str is not a number");
}

int a;
int b;

// Even if an exception is thrown, things are still ran until the end
// only then are the catch statements ran.
try(ConvException ex) {
   a = toInt("123") catch(ex);
   b = (toInt("345") catch(ex) + toInt("abc") catch(ex));
}
catch(ConvException ex)
{
    writeln(ex.msg);
    return -1;
}

On a similar vein, if we have that sort of catch expression shown above, we could possibly make our own version of if err != nil spam look even worse :D!

ConvException ex;

if(toInt("123") catch(ex) + toInt("abc") catch(ex) && ex.isError)
{
    writeln(ex.msg);
    return -1;
}

On the topic of function chaining, let me introduce you to this beauty that my head just came up with.

Exception1 a;
Exception2 b;
Exception3 c;

// "@a" means "capture any exception into `a` and go straight to the catch block if something was thrown.

try someValue.func1()@a.func2()@b.func3@c
catch(a){}
catch(b){}
catch(c){}

(Don't ever let me design my own language).

But the point is, if we want to avoid Go's if-else spam, we need some other weird syntax to sugar on top of things.

Just why do we need new syntax? Can't we have it in terms of existing one?

Also proposed value exceptions look terribly similar to java checked exceptions, which are avoided in java world due to spamming issue it causes when trying to propagate them across call chain up to location where it is caught. Having them in D is like importing a bad feature from java, at least in current version they are suggested.