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


Reply via email to