An Optional!T and the implementation of the underlying type's opUnary
aliak
something at something.com
Wed Jul 25 12:51:08 UTC 2018
Hi, I'm working on an Optional!T type that is a mixture of
Scala's Option[T] (i.e. range based) and Swift's and Kotlin's T?
(i.e. safe dispatching). I'm interested in hearing about
mutability concerns.
So I want operations on the optional to dispatch to the
underlying type T if it's present. So let's take opUnary as an
example, this is how it's currently implemented:
auto opUnary(string op)() {
return this.opUnaryImpl!op();
}
auto opUnary(string op)() const {
return this.opUnaryImpl!(op, const(T))();
}
auto opUnary(string op)() immutable {
return this.opUnaryImpl!(op, immutable(T))();
}
private auto opUnaryImpl(string op, U = T)() const {
import std.traits: isPointer;
static if (op == "*" && isPointer!U) {
import std.traits: PointerTarget;
alias P = PointerTarget!U;
return empty || front is null ? no!P :
some(cast(P)*this._value);
} else {
if (empty) {
return no!U;
} else {
return some(mixin(op ~ "cast(U)_value"));
}
}
}
(functions "some" and "no" are type constructors which return an
Optional!T of whatever the argument type is - except "no" needs
an explicit T argument)
Why not "opUnary(string op)() inout"?
The reason it's like this is because I want to transfer the
constness of "this" to the value T that is stored inside. If I
rewrite "opUnaryImpl()() const" as "opUnary()() inout" and remove
the implementation for mutable, const, and immutable, then this
works:
immutable a = Optional!int(3);
++a;
And the internal value is modified.
Should that be allowed?
The caveat is that 1) I want Optional!T to be nogc compatible. So
therefore the value is stored similarly to this PR in phobos [1]
(also for an Optional type)
And 2) Optional!T provides an "unwrap" function that returns a T
(if T is a class or interface), or a T*. So, if I allow
modification by using inout on opUnary, then for the sake of
consistency, I should be able to do this:
immutable a = Optional!int(3);
a = 4;
But I can't do this because Optional.opAssign would be either
inout or immutable and I can't modify this.value = newValue;
And then what about:
auto a = Optional(immutable int)(3);
a = 3; // should this be allowed?
If it is allowed then this will fail because of the nogc
requirement:
unittest {
Optional!(immutable int) a = some!(immutable int)(5);
immutable(int)* p = a.unwrap;
assert(*p == 5);
a = 4;
assert(*a.unwrap == 4);
assert(*p == 5);
}
Comments, suggestions, opinions?
Cheers,
- Ali
[1] https://github.com/dlang/phobos/pull/3915
More information about the Digitalmars-d
mailing list