Thread overview
Question mark operator proposals
May 12, 2023
Dadoum
May 12, 2023
FeepingCreature
May 12, 2023
zjh
May 12, 2023
Basile B.
May 12, 2023
Dadoum
May 12, 2023

There were at some point discussions in the forum about error handling and adding a potential question mark operator in D, and I would support it personally since it would allow to force caller of a function to handle some recoverable errors which can happen frequently (especially with @mustuse).

With current sumtypes, we can already do some cool stuff, and I am already using them for that, but I think that a question mark operator (or any other symbol if it conflicts with ternary syntax) as Rust does would be a nice addition to allow more flexibility and readability. To make things simple, maybe opUnary can be reused as such (or not, maybe the rewrite happens earlier, then opQuestion should do the job I guess):

struct ServerError {
    int error;
    string message;
}
alias ServerResponse = SumType!(string, ServerError);

bool opUnary(string op = "?")(ServerResponse response, out string content, out ServerError error) {
    return response.match!(
            (string res) => (content = res, true),
            (ServerResponse err) => (error = err, false),
    );
}

Otherwise, a special function could also work (but currently there is no way to make this kind of a macro-like functions in a D library, and I can't think of any syntax that could allow this in a clean way) which would look more integrated to D than question mark.

// Passing error handling a potential UI layer

// with question mark.
Account account = AuthServer.authenticate(mail, password)?;
// with a function.
Account account = AuthServer.authenticate(mail, password).propagate;
// maybe a bit long? `handle` is vague, and abbreviations would probably make the code unclear.
May 12, 2023

On Friday, 12 May 2023 at 13:02:25 UTC, Dadoum wrote:

>

There were at some point discussions in the forum about error handling and adding a potential question mark operator in D, and I would support it personally since it would allow to force caller of a function to handle some recoverable errors which can happen frequently (especially with @mustuse).

...

struct ServerError {
    int error;
    string message;
}

alias ServerResponse = SumType!(string, ServerError);

Account account = AuthServer.authenticate(mail, password)?;

Neat also has this (https://neat-lang.github.io/manual.html#sum-type):

struct ServerError {
    int error;
    string message;
}

alias ServerResponse = (string | fail ServerError);

string account = AuthServer.authenticate(mail, password)?;

// More verbose form
string account = AuthServer.authenticate(mail, password)
    .case(ServerError err: return err);

fail is a keyword of sumtype entries. Any expression of the form x? will return all entries marked as fail, yielding a sumtype of the remaining types, or the type if there's only one.

It seems to work pretty well. The interaction with class methods is dubious though, because it means that a submethod cannot ever return an error that a supermethod didn't account for. (Arguably that's not wrong...)

May 12, 2023

On Friday, 12 May 2023 at 13:02:25 UTC, Dadoum wrote:

>

There were at some point discussions in the forum about error handling and adding a potential question mark operator in D, and I would support it personally since it would allow to force caller of a function to handle some recoverable errors which can happen frequently (especially with @mustuse).
...

Features that other languages have good grammar feedback, should be actively supported as D as a niche language unless it cannot be implemented.

May 12, 2023

On Friday, 12 May 2023 at 13:02:25 UTC, Dadoum wrote:

>

There were at some point discussions in the forum about error handling and adding a potential question mark operator in D,

Sigh, yes I remember that topic.

This lead to an attempt but unfortunately that did not work.
A few links for those interested to understand what happened:

After all these years, I find that finally the most usefull variation is actually the
optional assignment

if (!a)
    a = b;
// becomes
a ?= b;

faster to lex and parse (9 tokens VS 4), easy to read, but the main asset is that it is reusable in subexpressions, e.g call arguments. The optional assignment is my favorite niche expression lately.

May 12, 2023

On Friday, 12 May 2023 at 13:02:25 UTC, Dadoum wrote:

>
        (ServerResponse err) => (error = err, false),

By the way, that's a typo I should have written ServerError