Alternatives to exceptions for error handling

Adam D. Ruppe destructionator at gmail.com
Mon Nov 23 02:48:10 UTC 2020


On Sunday, 22 November 2020 at 17:37:18 UTC, Roman Kashitsyn 
wrote:
> 1. A sum type that contains either a result or an error.

I think it would also be good to have implicit construction of 
return value.

Sum!(Error, Result) foo() {
     return Error(0);
}

That's currently an error, you must explicitly mention the return 
type by name or by typeof return.

return typeof(return)(Error(0)); // works, but wordy

Of course you can alias the sum type,

alias EC!T = Sum!(Error, T);

EC!Result foo() { return EC!Result(r); }

but still.

So if the compiler would automatically insert that constructor 
call, when necessary, it'd probably make it a lot easier to use. 
You can still just return normal stuff syntax-wise.


> 2. Some kind of syntactic sugar for propagating errors upstream 
> (? macro in Rust, check/handle proposal in Go 
> https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling.md, an ugly macro in C++, etc.).

Yes, the ? thing in rust is pretty cool.

I was thinking about this earlier today too and perhaps reusing 
the `try` or `catch` keywords could do it as well.

But what I'd like to do is have it work with user-defined types 
too, not just compiler magic. So it expands into something like:

// you write
auto r = foo()?; // or auto r = try foo(); or whatever syntax

// and it becomes:
auto tmp = foo();
if(auto error = tmp.opError())
     return error;

auto r = tmp.opValue();


Where the opError and opValue are just defined names, similar to 
operator overloading, that any type can define.


Combined with the above implicit return construction and other 
existing D features, this would enable a lot of things. For 
example:

---
struct null_is_error {
         void* ptr;
         int opError() { ptr is null ? .errno : 0; }
         auto opValue() { return ptr; }
}

import core.stdc.stdlib;

ErrnoOr!(void*) main() {
         auto p = malloc(5).null_is_error?; // note Rust-style ?
}
---

This expands into:

---
auto tmp = malloc(5).null_is_error; // UFCS ctor call of helper 
btw
if(auto err = tmp.opError())
     return err; // which implicit constructs into return 
typeof(return)(err);
auto p = tmp.opValue();
---

So we're able to paint on new features to old functions, adapt to 
a variety of error schemes (could even use classes like our 
current exceptions!) as needed for any user, not just a 
compiler-recognized magic type, and be able to write it 
reasonably conveniently.


More information about the Digitalmars-d mailing list