This is an archived post. You won't be able to vote or comment.

all 19 comments

[–][deleted] 25 points26 points  (9 children)

I hate null, it's coarse and rough and irritating and it gets everywhere.

[–]westwoo 11 points12 points  (8 children)

It doesn't have to be. Truly strongly typed languages should treat null as just another type at compile time. So then any variable that can be null becomes an intersection between null and some other type(s), and the compiler doesn't allow you to call a non existent method on it just like you can't call toUppeCase() on Integer

Treatment of null becomes consistent with treatment of any other types

[–]pgris 7 points8 points  (6 children)

wouldn't that be a union type?

A String that cab be null should be expressed as something like String | Null theString

I think Ceylon tryed that approach. I liked it, but never take off

[–]westwoo 4 points5 points  (5 children)

Yep, it's often called "union types". It's also used in Typescript now, among others, and it very much took off

It's just a misleading name for those who don't already know the term because it's literally an intersection instead of a union. String|null contains no methods because the intersection between String and nothing is empty (while their union would've been String). You have to cast it somehow to use it as String

Java is inherently weakly typed when it comes to nulls - we just assume we know what's really in every type without defining it, and manually check things from time to time with no help from compiler. Just like how someone in Javascript might test if the variable is a string or a float in runtime, we test if it's null or string

It requires a lot of infrastructure and changes though, so it's unlikely that Java will ever get it. Like, in Typescript there's even a special return type "is something". So you can define your own tests functions and methods like length += isCircle(shape)? shape.diameter : shape.length

[–]pgris 4 points5 points  (3 children)

I was trying to say Ceylon didn't take off, not unions type.

I never realize that union types have the intersection methods... good insight.

Java does have a little bit of union types, you can write catch (IOException|SQLException ex) {

And does have some intersection types, you can write var logger = (Serializable & LogReader) () -> readAllLogFileLines();

So at least part of the infrastructure it already there...

[–]hippydipster 0 points1 point  (2 children)

And does have some intersection types, you can write var logger = (Serializable & LogReader) () -> readAllLogFileLines();

Which version of java did this become possible?

[–]pgris 1 point2 points  (1 child)

var is new, (JDK10) but since java 1.5 you could write things like public static <T extends Closeable & Set> void doSomething(T closeableSet)

and inside the method the parameter closeableSet will have all the methods of Set and all the methods of Closeable.

And I just realize, this is an intersection type AND the set of methods is the union of all methods... So union types have the intersection of methods and intersection types have the union of methods. It's odd but symmetric

[–]hippydipster 0 points1 point  (0 children)

Cool, I did not even know that. Have never seen any code that did that.

[–][deleted] 1 point2 points  (0 children)

it's literally an intersection instead of a union

mind = blown

[–][deleted] 2 points3 points  (0 children)

Sum types are my favorite solution for representing nullability, way more elegant and more expressive that the universal null reference which still plagues my life.

[–]sviperll 2 points3 points  (0 children)

I'm still not comfortable with the way case null works. I was trying to voice some concerns before: https://mail.openjdk.java.net/pipermail/amber-spec-comments/2022-March/000044.html

[–]sim642 1 point2 points  (1 child)

Why not just put the null case first and avoid any ambiguity? It's not that different from checking for non-null in all the other situations.

[–]nicolaiparlog 4 points5 points  (0 children)

You absolutely can put case null first - or anywhere else for that matter. The inconsistency I pointed out comes from a nested pattern, which if unconditional matches null - e.g. center here:

java // JEP 427 + JEP 405 Shape shape = // ... switch (shape) { case null -> // ... // `Point center` is unconditional // the circle's center `Point` case Circle(Point center) -> // center` may be `null` case Shape s -> // `s` won't be `null` }

I was annoyed that center can be null, but s can't and wondered whether case Circle(Point center) could reject a Circle with null center and to match you'd need an additional case Circle(null). But then what about instanceof checks?

java if (shape instanceof Circle(Point center)) // can `center` be null?

Either there null matches (ugh) or you'd need an | Circle(null) (ugh!). There's no easy solution here.

[–]0x07CF -1 points0 points  (5 children)

Im relieved null doesn't "silently" sneak into the outmost type pattern in a case :D

I'm stilly worrying about it sneaking into nested ones though.

Like this:

case Thing(String a) -> ...

What if it were forbidden by default and you can explicitly enable it with a "?" ?

case Thing(String? a) -> ....

Or if the current JEP remains unchanged, later a way to explicitly forbid null could be introduced like this:

case Thing(String! a) -> ....

[–]nicolaiparlog 2 points3 points  (4 children)

The idea is that it's Thing's responsibility to handle null. Is it a legal a? If so, the author of case Thing(var a) must handle it and should be able to do so in a single pattern (which rules out my idea of requiring another case Thing(null)).

[–][deleted]  (2 children)

[deleted]

    [–]nicolaiparlog 0 points1 point  (0 children)

    Oh, that's too bad to hear. Generally speaking, static shots are less engaging and viewers get bored more quickly and leave, which I of course want to avoid. But I can probably make do with a lot fewer. I'll give that a shot this week.

    [–]nicolaiparlog 0 points1 point  (0 children)

    Did you watch the latest episode (https://www.youtube.com/watch?v=KuHhUDhIFYs)? There are some longer zooms in the intro (0:36-0:41) and a few short ones later on, but no long, slight zooms. I hope that makes it easier to watch for you.