On Saturday, 29 February 2020 at 12:50:59 UTC, Adnan wrote:
I have a struct that has to arrays. Each of those must have the same sizes.

So while constructing the array, if you pass two arrays of different sizes the constructor must return nothing.

In Rust I could easily use Option<T>. D has no answer to Optional types as far as I am concerned. Is throwing exceptions the only idiomatic way?


---

What I already considered:

* Using Nullable!T: Okay but Nullable!T has all the overloads for regular T which makes the API even more unpredictable.

In Rust you don't just add a Some(44) and 34; No overloads for Some<T> and i32 are allowed (purposefully).

* Option!T from the optional package: Has even worse problem IMO. Not only it allows None + int but also it returns a `[]`. This API is not to my liking. You could say well Haskell has fmap for Optional etc, and I am aware of that, so does Rust with map etc. But I am talking about basic things: like `+`.

* Value-based error handling like Go and C: well, that works but the error checking is opt-in. There's no such thing as [[nodiscard]] in D too so the user of the API might as well forget to check for error value.

* if specialization: Clever workaround but sometimes the struct may fail for complex reasons, not only for a single condition.

There's no idiomatic way since D lang is based on exceptions...

However I'd use one of those system:

1. return error, write result in ref parameter.

alias CheckedValueProto(RT, P...) = bool function(ref RT, P params);

2. the same using a special struct and no more ref param. So more like Nullable/Optional but with a dedicated generic type that contain a single opover used to indicate if there's been an error or not.

    struct CheckedValue(T) {
        bool noError;
        T t;
        B opCast(B : bool)() inout pure nothrow @safe {
            return noError;
        }
    }

and you make your functions to return CheckedValues...

    CheckedValue!int strToInt(string input);
    ....
    if (const CheckedValue!int = strToInt("a") {} else {}

Although
- both still require self-discpline or a specialized linter to detect unchecked calls ;
- the whole standard library is incompatible ;

I have a personal preference for 2. even if it causes problems when T is of same size as a pointer. Now the question is also what's the more costly ? try/catch or this non atomic return ?

Reply via email to