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?