Current sentiment on Nullable.get
aliak
something at something.com
Sat Dec 15 09:11:37 UTC 2018
On Saturday, 15 December 2018 at 02:14:15 UTC, Jonathan M Davis
wrote:
> On Friday, December 14, 2018 5:05:51 PM MST Rubn via
> Digitalmars-d wrote:
>> On Friday, 14 December 2018 at 23:08:30 UTC, Jonathan M Davis
>
>> So for this naturally nullable type, would you say it has a
>> value?
>>
>> int* ptr = null;
>
> It has the value of null, which can either have a distinct
> meaning unto itself, or it could mean that the pointer doesn't
> contain a value. Which it is depends on what the code is doing.
> For example, IIRC, SQL treats a value that is NULL and a value
> which doesn't exist as two separate states. Plenty of other
> code would consider null to be an invalid value.
>
> Without Nullable, if you wanted null to indicate that there is
> no value, then T* represents that just fine, whereas if you
> wanted null to be a valid value, then you'd need T** so that
> whether the outer pointer was null could be used to indicate
> whether a value was present. With an Optional or Nullable type,
> it's then possible to replace the T** with Nullable!(T*) in the
> case where you consider null to be a valid value, and if you
> considered null to be invalid, then either Nullable!T or T*
> would work, though T* would require a heap allocation.
>
>> > n = value;
>> > return n.get;
>> >
>> > could then actually fail the assertion in get if the code
>> > was instantiated with a type that was naturally nullable.
>> > The current approach - regardless of the name of Nullable -
>> > prevents that problem.
>>
>> When would you ever want to use get() if you know isNull is
>> true
>> (including for if isNull() returned true for pointers that
>> have a
>> null value) ?
>
> The problem I'm pointing out is that if isNull cares about
> whether the value the Nullable contains is null, then you can
> no longer rely on the fact that a Nullable has been assigned a
> value to determine whether get is legal to call (at least not
> in generic code). You would always have to call isNull first,
> because the value it was assigned might have been null if that
> code had been instantiated with a type that can be null.
> Currently, something like
>
> n = value;
> foo(n.get);
How is this code realistic? Why would anyone assign a value to a
Nullable inside a scope where they can see the code and then pass
it as get to a function. And if you were getting the Nullable
from a different scope then why would you ever call get without
checking isNull first. The only place code would break is if
people considered null a valid value with operational semantics
for T*. This is also something I think is valid usage because
like you say, Nullable!(T*) make zero sense otherwise. But it
make zero sense for Nullable!Class to treat null as a valid
value. Contrary to what you are saying, it makes generic code
MORE complicated.
In generic code if I get a Nullable!T* I know I need to check
whatever get returns is null or not. With any other T which could
be a reference type it complicates my code.
>
> On the other hand, right now, because Nullable works the same
> regardless of what type it containts, it works quite well in
> generic code, and because Nullable!(T*) basically gives you T**
> without the extra heap allocation, there are use cases where it
> makes sense to use Nullable!(T*) even though T* is already
> nullable. So, ultimately, the way that Nullable currently works
> makes sense, whereas having isNull be affected by the value
> contained by the Nullable does not. It could certainly be
> argued that the naming is poor, but the semantics are exactly
> what they should be.
I think I understand what the problem is now. You keep on
interchanging Nullable!(T*) with just plain Nullable. And if we
are only talking about Nullable!(T*) then I can agree with what
you say. But generic code is not just T*'s and when it's not T*s
then it makes zero sense for isNull to return false if the value
is a null ref type.
Cheers,
- Ali
More information about the Digitalmars-d
mailing list