On my experience programming using Optional's functional
interfaces is more reliable then explicit logic, so in case when
we have value semantic and Optional then Kotlin's approach is not
very useful.
My old experiments about this (obviously java-inspired):
optional.d
import std.typecons;
import std.stdio;
Nullable!T Optional(T)(){ return Nullable!T(); }
Nullable!T Optional(T)(T value){ return Nullable!T(value); }
Nullable!OUT map(IN, OUT)(Nullable!IN n, OUT delegate(IN) fn)
{
return n.isNull() ? Nullable!OUT() :
Nullable!OUT(fn(n.get()));
}
T orElse(T)(Nullable!T n, T value){ return n.isNull() ? value :
n.get(); }
void ifPresent(T)(Nullable!T n, void delegate(T) fn){
if(!n.isNull()) fn(n.get()); }
void ifPresent(T)(Nullable!T n, void function(T) fn){
if(!n.isNull()) fn(n.get()); }
bool isPresent(T)(Nullable!T n){ return !n.isNull(); }
Nullable!T coalesce(T)(Nullable!T n, Nullable!T other){ return
n.isNull() ? other : n; }
unittest
{
assert(Optional!string().isNull());
assert(Optional!string("asd").isPresent());
assert(Optional!string("asd").map((string v) => v~"$") ==
"asd$");
assert(Optional!string().map((string v) => v~"$").isNull());
assert(Optional!string("true").map((string v) => v=="1" ||
v=="true").orElse(false) == true);
assert(Optional!string().coalesce(Optional!string("test")) ==
"test");
assert(Optional!string("test1").coalesce(Optional!string("test2")) == "test1");
string a="-";
Optional!string("A").ifPresent((string b){a=b;});
Optional!string().ifPresent((string b){a=b;});
assert(a == "A");
}