Difficulties with std.variant.Algebraic
Meta
jared771 at gmail.com
Wed Jul 10 20:06:30 PDT 2013
I've been playing around with std.variant.Algebraic, trying to
define a very simple option type. However, I've been running into
quite a few problems. My implementation is as follows:
import std.conv;
import std.variant;
struct Some(T)
{
T payload;
alias payload this;
}
struct None
{
}
struct Option(T)
{
Algebraic!(Some!T, None) payload;
alias payload this;
}
Option!int unreliable(int val)
{
if (val == 0)
{
return None();
}
else
{
return Some!int(val);
}
}
Unfortunately, I can't return values of type Some or None from
"unreliable" and expect the compiler to know that they should
become an Algebraic wrapped in an Option. This is annoying, but I
can't expect magic. Maybe if I'm explicit:
Option!int unreliable(int val)
{
if (val == 0)
{
//Nope
return cast(Option!int)None();
}
else
{
//Nope
return cast(Option!int)Some!int(val);
}
}
Option!int unreliable(int val)
{
if (val == 0)
{
//Nope
return cast(Option!int)None();
}
else
{
//Nope
return cast(Option!int)Some!int(val);
}
}
Option!int unreliable(int val)
{
if (val == 0)
{
//Nope
return cast(Algebraic!(Some!int, None))None();
}
else
{
//Nope
return cast(Algebraic!(Some!int, None))Some!int(val);
}
}
Okay, I'll try constructing a fresh struct and returning that:
Option!int unreliable(int val)
{
if (val == 0)
{
//Nope
return Option!int(None());
}
else
{
//Nope
return Option!int(Some!int(val));
}
}
One final, last-ditch effort:
Option!int unreliable(int val)
{
if (val == 0)
{
return Option!int(cast(Algebraic!(Some!int, None))None());
}
else
{
return Option!int(cast(Algebraic!(Some!int,
None))Some!int(val));
}
}
Yes! It worked. The only problem is that this is completely
unacceptable to type. The only other solution I can think of
would be to define constructors for Option that take a Some and a
None. I suppose it's not *all* bad, though. I mean, it compiles...
void main()
{
auto maybeNone = unreliable(10);
//Error: template std.variant.visit cannot deduce template
function from argument types !()(Option!(int))
assert(maybeNone.visit!((Some!int s) => text("Value is ", s),
(None n) => "No value")
== 10);
}
I don't know whether to laugh or cry.
More information about the Digitalmars-d-learn
mailing list