Live data from Hacker News

New Features in Java 14

blogs.oracle.com

181–188 of 188 posts

Re: New Features in Java 14

#181
post #176

Earlier quoted context omitted.

It's not really clear from your description as to what's wrong with Optional type. When Java would introduce value classes, I could imagine Optional class to be automatically transformed by a JIT to a nullable instance removing all overhead. Why do you want to keep null inside Optional? That would be absolutely non-intuitive design.

The most basic example of the problem with null is: if you call Map.get(key) and get null back, you don't know whether that means the map doesn't contain a mapping for key, or it contains a mapping from key to null. Optional lets you solve this: if we added a Map.getOption(key) that returns an Optional then it will be None if the map doesn't contain a mapping for key, and Some(null) if the map contains a mapping from…

When you're calling `Map.get(key)`, you're getting null both for case when value is null and for case when value is missing. If you need to distinguish those cases, you have to use `contains(key)`. That's questionable design for sure and it's generally recommended to avoid null values. But Optionals have nothing to do with that.

If you ask me, they should have introduced another class, something like NullableOptional, similar to Optional for those use-cases. I don't agree that putting `null` in every optional just because of few bad APIs is a good idea, because people use Optional exactly to avoid dealing with nulls.

Re: New Features in Java 14

#182
post #157
post #70

Earlier quoted context omitted.

I was in a Java shop at one point where leadership said Kotlin would be too hard for the engineers to learn (they were all mostly fairly junior).

Syntax is not that different from Java. Someone who knows Java could be productive in 1-2 days. But it sounds like you agree that your leadership in that scenario was not rational.

I'm not sure, I never tried Kotlin.

I like the look of it but I know Java pretty well so it's been hard to not just use that for my personal stuff :p

Re: New Features in Java 14

#183
post #176

Earlier quoted context omitted.

The most basic example of the problem with null is: if you call Map.get(key) and get null back, you don't know whether that means the map doesn't contain a mapping for key, or it contains a mapping from key to null. Optional lets you solve this: if we added a Map.getOption(key) that returns an Optional then it will be None if the map doesn't contain a mapping for key, and Some(null) if the map contains a mapping from…

When you're calling `Map.get(key)`, you're getting null both for case when value is null and for case when value is missing. If you need to distinguish those cases, you have to use `contains(key)`. That's questionable design for sure and it's generally recommended to avoid null values. But Optionals have nothing to do with that. If you ask me, they should have introduced another class, something like NullableOptional…

> That's questionable design for sure and it's generally recommended to avoid null values. But Optionals have nothing to do with that.

On the contrary, a selling point of Optionals is that they let you avoid that problem. Like I said, you could have a Map.getOption(key) function that unambiguously tells you whether the value is present or not, because it only ever returns None for absence, and will always return Some(value) (which might be Some(None) or Some(null), but those can be distinguished from None) if the value is present.

> I don't agree that putting `null` in every optional just because of few bad APIs is a good idea, because people use Optional exactly to avoid dealing with nulls.

Optional should be a transparent, consistent class that can contain any value that's valid in the language. Maybe Java will eventually reach a point where null can be considered invalid, but until that day, having Option ban putting null in it because it's old and deprecated makes about as much sense as if ArrayList banned you from making lists that contained deprecated classes.

Re: New Features in Java 14

#184
post #45
post #7

Earlier quoted context omitted.

Scala does a pretty good job too, with the help of build plugins you can avoid null polution (which normally comes from Java libraries) pretty well.

Build plugins - do you mean wartremover or something else?

Yes Wartremover, Scalastyle, Codacy, Scalazzi all help with this to varying degrees

Re: New Features in Java 14

#185

Earlier quoted context omitted.

Yes, the difference is a combination of types being non-null by default and compiler enforced checking. This doesn't require an option type. Option types are actually quite awkward compared to language integration. Kotlin doesn't use an Option type yet still delivers all the same benefits as Rust/Haskell's approach, with benefits (e.g. zero overhead, integrated syntax). Note that Option type overhead isn't merely abo…

Doesn't that approach make the "nothing branch" extremely expensive? Makes sense in scenarios where you really always expect Something and not Nothing. In practice, Options are very often used where something is optional, and you can expect to get Nothing a good percentage of the time. Using exceptions in such cases seems silly.

Yes if you expect nothing, you test for it obviously. The problem is when you want high quality errors for the case where you didn't expect it and you e.g. casted away the nullness, or it was casted away for you due to language interop.

Re: New Features in Java 14

#186

Earlier quoted context omitted.

I was responding to the following post: > The key difference is that in your second example you can just forget about the else branch, while in Rust you must explicitly handle the None case, otherwise it won't compile. Do you really think that `unwrap()` is meaningfully different from "forget[ting] about the else branch"? Does it require you to " explicitly handle the None case"? My goal here was not to get mired in…

Yes, it absolutely is different. The naive code will not have unwrap() in it, and it will fail to compile. At that point the developer can still mistakenly use unwrap() to unblock themselves, but it's still opt-in, not opt-out. If you're implying that coders use unwrap() pre-emptively, I don't think there's any evidence for that. Besides, you can't just slap it on every value you have - it must actually be a result t…

I think you agree with me but are convinced that we do not agree because of minor differences in wording.

Re: New Features in Java 14

#187

Earlier quoted context omitted.

Isn't unwrap(x) just match x { Some(v) => return v None => die painfully } ? If so, the None is still handled. Dying painfully is an escape hatch out of the type system in any language that lets you do it.

I was responding to the following post: > The key difference is that in your second example you can just forget about the else branch, while in Rust you must explicitly handle the None case, otherwise it won't compile. Do you really think that `unwrap()` is meaningfully different from "forget[ting] about the else branch"? Does it require you to " explicitly handle the None case"? My goal here was not to get mired in…

I get the thrust of your argument (that the expressiveness of the type system is what matters here), and it makes sense to me.

I'm not sure I agree with this though:

> Do you really think that `unwrap()` is meaningfully different from "forget[ting] about the else branch"? Does it require you to "explicitly handle the None case"?

I haven't used Rust, so but digging up the source shows unwrap is indeed just a `match` that panics on None.

The fact that "you can put thing inside a function and call that function" doesn't mean you "don't have to explicitly do thing". We end up with a pretty useless standard for "explicitly doing thing" if putting thing in a function doesn't count.

Re: New Features in Java 14

#188

I wonder about records - they would be great for simplified implementation of immutability, but they seem to not provide a way to copy with a subset of modified fields - like in Scala: case class Person ( firstName: String, lastName: String, age: Int ) you could create an instance like this: val emily1 = Person("Emily", "Maness", 25) and then create a new instance by updating several parameters at once, like this: //…

It is very cumbersome to not having the 'copy' or equivalence so that a lot of functional languages have similar things: F#: let updated = { old with prop = newValue } Elixir: update = %{ old | prop: newValue } Even JavaScript have similar stuff: const update = { ...old, prop: newValue }

Clojure: (assoc old :key new-value)

just a fn in the end

Post reply on HN