Hi,
On 5/8/19 7:16 PM, John Rose wrote:
On May 7, 2019, at 11:37 PM, Peter Levart <[email protected]> wrote:
On 5/2/19 12:29 AM, John Rose wrote:
Regarding subtyping, I don't see (from these considerations)
a firm reason to declare that V? is a super of V. The value
set of V?*might* have one more point than that of V,
or it*might not*. The reason we are doing V? is not the
value set, but the whole contract, which includes the
value set as an obvious, but ultimately non-determinative part.
Just one observation...
If inline class V was declared to support a "kind" of null (default, sentinel)
value by itself, then how such value would be denoted?
Is this a way?
V v = null;
Yes, because there's only one null in the whole world.
(The possibility of having many kinds of null, perhaps
one per type, is something we are trying to avoid.
Null is a costly feature, sometimes referred to as a
billion dollar mistake[1]. We have to deal with it
in Java. Adding more of them would be even more
costly IMO.)
[1]:
https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare
A really good and though provoking talk. In particular I liked the part
where Tony Hoare compares flow control abstractions in high level
languages (loops, if-then-else, exceptions) with data structure
abstractions. The machine level building block for the first is jump
instruction, while for the second a pointer.
While there are several different flow control abstractions, there's not
much that is abstracted about pointers in high level languages. V vs. V?
seems to be an abstraction in that direction that is just approximately
tied to the machine level implementation.
So a question arises whether to allow calling instance methods on null V
or to runtime check for null (sentinel) value and throw NPE at call site.
Since null (sentinel) value of null capable V is represented by a real
state, it should be possible for instance methods to operate on that
state, but...
If this was possible, then what would be the distinction between the following
two then?
V? vInd1 = null;
V? vInd2 = v;
Would vInd1 and vInd2 represent the same "null" value?
Yes, please please please.
... what should be the outcome of invoking an instance method on a null
V? then?
If you allow calling instance method on a null V:
V v = null;
v.m(); // OK
Then the following becomes confusing for the user:
V v = null;
v.m(); // OK
V? vInd = v;
vInd.m(); // NPE or OK ?
You might implement the 2nd call to operate on a re-constructed null
(sentinel) state of V in that case, but then throwing NPE or not becomes
a matter of whether V is null-sentinel capable or not, because you can
not construct null state when V does not declare that capability.
So the only consistent behavior seems to be to always throw NPE on null,
which might involve runtime check for null sentinel state.
Regards, Peter