Hacker News new | ask | show | jobs
by cletus 168 days ago
The mistake was not having nullability be expressed in the type system.

At Facebook I used their PHP fork Hack a lot and Hack has a really expressive type system where PHP does not. You can express nullability of a type and it defaults to a type being non-nullable, which is the correct default. The type checker was aware of changes too, so:

    function foo(?A $a): void {
      $a->bar(); // compile error, $a could be null
      if ($a is null) {
        return;
      }
      $a->bar(); // not a compiler error because $a is now A not ?A
      if ($a is ChildOfA) {
        $a->childBar(); // not an error, in this scope $a is ChildOfA
      }
    }
Now Hack like Java used type erasure so you could force a null into something non-nullable if you really wanted to but, in practice, this almost never happened. A far bigger problem was dealing with legacy code that was converted with a tool and returned or used the type "mixed", which could be literally anything.

The real problem with Java in particular is you'd end up chaining calls then get the dreaded NullPointerException and have no idea from the error or the logs what was broken from:

   a.b.c.d();
I'm fine with things like Option/Maybe types but to me they solve different problems. They're a way of expressing that you don't want to specify a value or that a value is missing and that's different to something being null (IMHO).
4 comments

Yeah in Typescript I rarely run into null deference errors at runtime either. It can happen if you unsafely cast the type of values coming into your code, but if you runtime validate input at your application boundary it’s very unlikely

Now looking back at a lot of other languages that don’t express nullability, it’s like, what were they thinking? How did I not wish for nullability in type declarations in all my years of dealing with NullPointerExceptions?

> The real problem with Java in particular is you'd end up chaining calls ... and have no idea from the error or the logs what was broken from: a.b.c.d();

That’s been solved since Java 14. (5 years ago) Now the error will tell you exactly what was null.

And “soon” Java will have built in support for expressing nullability in the type system. Though with existing tools like NullAway it’s already (in my opinion) a solved problem.

Exactly, null is not evil it itself – the fact that it's not represented in type system is.

Type system where nullability can be expressed, you have refinement so you can map "null | T" to "T" with conditionals and sugar like optional chaining and nullish coalescing is all that's needed.

Neat.

In PHP land, for some years now that code would not pass CI/CD checks and IDEs show red squiggles. Provided they use any popular static analysis tools like PHPStan, Psalm and I believe SonarQube would also flag it.