Programming Languages – Solutions to Represent Non-Initialized Objects Without Null

nullprogramming-languages

This comes with a debate with my colleague that I'm using null as an object initial state.

type Value = Node | null
const [value, setValue] = React.useState<Value>(null)

function test(v: Value) {
  if (value === null) // Do something
  else // Do something
}

I'm curious if null is a mistake in this case. What alternatives are there to represent an object that is not (yet) initialized?
And how is this solved in languages that don't support null pointers?

Note: This question is similar to If nulls are evil, what should be used when a value can be meaningfully absent? – the difference is that that question is about cases where a value is truly absent/not relevant – whereas here the question is about a value where initialization has been delayed, because the value will be produced/retrieved later.

Best Answer

The problem isn't null itself. It's the implicit nullability of all object references, as is the case in Java, Python, Ruby (and previously C#, although that picture is changing).

If you have a language where every type T really means T | Null. Suppose you had a system that takes such a nullable reference at its entry point, does some null checking, and wants to forward on to another function to do the "meat" of the work. That other function has no possible way to express "a non-null T" in Java (absent annotations), Python or Ruby. The interface can't encode its expectation for a non-null value, thus the compiler can't stop you from passing null. And if you do, fun things happen.

The "solution" (or "a solution", I should say), is to make your language's references non-nullable by default (equivalently, not having any null references at all, and introducing them at the library level using an Optional/Option/Maybe monad). Nullability is opt-in, and explicit. This is the case in Swift, Rust, Kotlin, TypeScript, and now C#. That way, you clearly distinguish T? vs T.

I would not recommend doing what you did, which is to obscure the nullability behind a type alias.