Feedback on Null-Restricted and Nullable Types
Brian Goetz
brian.goetz at oracle.com
Wed Sep 11 00:27:53 UTC 2024
On Sep 10, 2024, at 5:43 PM, Olexandr Rotan <rotanolexandr842 at gmail.com<mailto:rotanolexandr842 at gmail.com>> wrote:
I would argue that not the syntax around nulls should be hideous, but rather non-null should somehow be the default option
We’re going to get this suggestion a lot. It is pretty clear that “non-null” is a better default interpretation of an otherwise unannotated type name than “nullable” is; this results in a lower annotation burden for annotating old code, less visual noise for reading fully annotated code, a safer default, etc. And if we were designing a language from scratch, it would be pretty hard to argue against this.
But as you acknowledge, there are billions of lines of Java code out there, and retroactively changing their meaning is a non-starter. People will surely suggest things like “what about a compiler flag” (please don’t), but that’s just forking the language and pretending we aren’t. And all the “obvious” suggestions have one or both of these characteristics.
So, we truly understand how this would be yet another “Java got the defaults wrong”. And maybe there is a path — in the not-so-immediate-future — to opting into stricter null checking in a way that does not feel like a fork. And we’re going to think about that, and if we find something that seems acceptable, we’ll consider it. But as James says, if you don’t know the right thing to do, then the right thing to do right now is to do nothing. So we will not be tackling the “wrong default” problem at the same time as we are addressing null restriction. (Besides, there’s enough impossible problems in Valhalla that we don’t need to add another one onto our plate.)
, so people will not bother adding anything on top of that unless explicitly needed. I'm not really sure if it's achievable with preserving source backward compatibility though, given that currently, default is unspecified nullability. I think that many people will bother adding ! as much as ?, honestly. Most of the production code I have worked with didnt even care about returning an unmodifiable view of collection instead of the real one or wrapping nullable value in optional in getters and hiding no-args constructors in POJO using protected keyword. Honestly, the sad truth (in my experience) is the fact that if something is not done by default, it will not be done manually in the vast majority of cases, no matter how potentially beneficial it is. I would say that best option would be to introduce compiler flag that enables non-null by default, and eventually, after most users are migrated, make it true by default.
Regarding new null in language. I (unfortunately) spend at least half of my working with typescript. To say that this null-undefined fuss is terrible is to keep silent. That's just a complete mess. Question mark in type stands only for type | undefined, want to accept null - go and do var?: type | null - just terrible. Question mark notation in field access chains is also so strange: it, contrary to ? in type, accepts both null and undefined, and it often leads to confusing situations when you expect one of those two, but get another, logic in ?? still executes, and your erroneous state passes down through long chain of invocation until it finally fails somewhere and good luck debugging it/ Two different nulls is just a horrible idea in so many ways.
PS: Nothing bad with nulls by themself. Absence of value is also a value in many scenarios
On Tue, Sep 10, 2024 at 8:46 PM Brian Goetz <brian.goetz at oracle.com<mailto:brian.goetz at oracle.com>> wrote:
The following was received on valhalla-spec-comments.
Point #1 rests on an assumption that the goal of this feature is to eliminate, or at least strongly discourage, nulls. This is a common assumption — many people are so-called “null haters” — but encouraging or rewarding such biases is not the role of the langauge. Nulls are not intrinsically bad; the problem with nulls is that they are so often unexpected, and so people code as if they would never happen. Reflecting nullity in the type system allows you to reason about when they are expected, and make reasoned choices about where nulls are appropriate or not.
You state your position pretty explicitly here:
>> The syntax to use null must be "disgusting enough" in order to
>> discourage people from using it.
I’m not going to criticize your opinions about nulls, but it is also OK to have different opinions about nulls, and it’s not the role of the language to insist that one or the other is the only valid set of feelings about it.
Your second point is what we call “inventing a new null”; it is a tempting answer, but is overwhelmingly likely to just make the problem worse, because now there are two ill-behaved states.
> On Sep 10, 2024, at 10:46 AM, Enrique <enrique.arizonbenito at gmail.com<mailto:enrique.arizonbenito at gmail.com>> wrote:
>
> REF: https://openjdk.org/jeps/8303099
>
> Feedback 1:
>
> Using the syntax "Foo?" for nullables values does not discourage the
> use of nulls in code.
>
> In my experience working with Kotlin, novice (and not so novice)
> developers just find themselves comfortable enough adding an extra
> character and continue to infest code with nulls.
>
> The syntax to use null must be "disgusting enough" in order to
> discourage people from using it.
>
> For example something like Foo!!!NullBackwardCompliant!!!. This syntax
> is ugly enough to scare people about using it.
>
>
> Feedback 2:
> Most people naively tends to use null in next scenarios:
>
> * A class/record must be initialized, but due to the data flow, some
> of its members are not yet known in "present time". They depend on
> future input data/processing.
> * Some member must not take any value in a given context.
>
> Ideally the JVM would be extended to support "FUTURE" and "NA" (Not
> Apply) values in parallel to null. Any read must throw a
> FuturePointerException or NAPointerException.
> While the behaviour looks similar to the current null and
> NullPointerException, it makes error debugging much easier to
> understand:
> * A FuturePointerException promptly warns about some race condition:
> Some code tried to read a value before some process (maybe another
> thread) initialized it.
> * A NAPointerException promptly warns about some error in the business
> logic. Some code didn't contemplate the NA scenario.
>
> "catch" blocks will also be able to make much more sensible decisions
> (when compared to the pervert NullPointerException).
>
> Without any JVM extension, a compiler most probably can automate a
> similar behavior with a syntax similar to:
>
> var Foo1 = Future
> var Foo2 = NA
>
> Foo1 and Foo2 are **NOT** nullables.
>
> Foo2 becomes a constant (It will never change once defined and the
> compiler can make many verifications out of the box).
>
> Foo1 must never be read until a given value is provided (after which
> it will probably become constant).
>
>
> My two cents!
>
> Enrique Arizón Benito
> Software Gardener
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/valhalla-dev/attachments/20240911/8f4b9166/attachment-0001.htm>
More information about the valhalla-dev
mailing list