On Friday, 6 November 2020 at 10:51:20 UTC, Andrey Zherikov wrote:

struct Result(T)
{
    struct Success
    {
        static if(!is(T == void))
        {
            T value;
        }
    }
    struct Failure
    {
        string error;
    }

    Algebraic!(Success, Failure) result;

    this(Success value)
    {
        result = value;
    }
    this(Failure value)
    {
        result = value;
    }
}
auto success(T)(T value)
{
    return Result!T(Result!T.Success(value));
}
auto failure(string error)
{
    return Result!void(Result!void.Failure(error));
}

auto f(int i)
{
return i > 0 ? success(i) : failure("err text"); // Error: incompatible types for (success(i)) : (failure("err text")): Result!int and Result!void
}

I'd go with:

struct Result(T)
{
    Nullable!string error;

    static if(!is(T == void))
    {
        T value;

        static Result!T success(T value)
        {
            return Result!T(Nullable!string.init, value);
        }

        static Result!T failure(string error)
        {
            return Result!T(nullable(error), T.init);
        }
    }

    else
    {
        static Result!T success()
        {
            return Result!T(Nullable!string.init);
        }

        static Result!T failure(string error)
        {
            return Result!T(nullable(error));
        }
    }

    bool isSuccess()
    {
        return error.isNull();
    }
}

// Demo
Result!int intFun(int i)
{
return i > 0 ? Result!int.success(i) : Result!int.failure("Be positive!");
}

Result!void voidFun(int i)
{
return i > 0 ? Result!void.success() : Result!void.failure("Be positive!");
}

void main()
{
    auto intFunRes = intFun(5);

    if(intFunRes.isSuccess)
        writefln("Result: %d", intFunRes.value);
    else
        writefln("ERROR: %s", intFunRes.error.get);
}

Does this satisfy your needs?

Reply via email to