Live data from Hacker News

New Features in Java 14

blogs.oracle.com

171–180 of 188 posts

Re: New Features in Java 14

#171

Earlier quoted context omitted.

No that's not the key difference, because you can just call `unwrap()` and forget about it, which is effectively the same footgun as other languages. The key difference is that now the type system can tell you the truth. In other languages when you have a reference to a type T, null is considered a valid T but you cannot treat it as one or everything blows up. Meanwhile in rust when you have a reference to T, you don…

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 semantic arguments that ignore the context of the discussion. It was merely to highlight that Rust lets you assume that things won't be null the same as any other language, and that the important difference is that rust lets you be clear about what can and cannot be null.

Re: New Features in Java 14

#172
post #61

Earlier quoted context omitted.

Please do not quote posts out of context in order to make your argument seem stronger. > Please respond to the strongest plausible interpretation of what someone says, not a weaker one that's easier to criticize. Assume good faith. I am well aware of the issues in other popular languages. You and I agree that there is an implicit `unwrap()` call in each dereference operation. The post I was responding to claimed that…

When you write unwrap(), you're handling them - by forcing a panic, but it's still a choice that you make.

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 semantic arguments that ignore the context of the discussion. It was merely to highlight that Rust lets you assume that things won't be null the same as any other language, and that the important difference is that rust lets you be clear about what can and cannot be null.

Re: New Features in Java 14

#173
post #61

Earlier quoted context omitted.

When you write unwrap(), you're handling them - by forcing a panic, but it's still a choice that you make.

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…

> the same as any other language,

I think this is the point of contention. Languages with some Option type and no null are not the same as any other language. Yes, you can ignore error handling, but you cannot forget it.

Re: New Features in Java 14

#174

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…

> the same as any other language, I think this is the point of contention. Languages with some Option type and no null are not the same as any other language. Yes, you can ignore error handling, but you cannot forget it.

IMO handling forgetfulness is the job of the compiler and ties back into my overall point; that the meaningful distinction is the type system's awareness of what can or cannot be null.

I believe that claims that Rust forces you to not "forget about the else branch" are actively harmful to language adoption, I've seen many people use `unwrap()`'s existence as evidence that Rust's approach to empty value types doesn't actually provide any useful benefits.

Re: New Features in Java 14

#175
post #59

Earlier quoted context omitted.

Panicing is the right thing to do: fail-fast is much better than silently continuing in an invalid state. If the None state is valid then don't call unwrap() (which you should almost never use, because if None was not a valid state then why were you using an Option in the first place?), call a function that lets you handle both cases, e.g. unwrap_or.

It's sometimes the right thing to panic, in which case use the !! operator to cast away the nullness and get an NPE at that point (now a helpful one as the new Java feature is really a JVM feature!) With this new feature I'd argue the Java/Kotlin world now has the best handling of optionality of any language, anywhere: • Pleasant, concise syntax for handling optionality. Not bolted on with an option type. • Highly ef…

I have to disagree. This is an improvement, but it still leaves Kotlin behind where languages like OCaml were 20+ years ago, because nullable types don't compose the way you'd expect. (If you write generic code that uses T?, your code will break when T is itself a nullable type).

> • Pleasant, concise syntax for handling optionality. Not bolted on with an option type.

Optionality is not special enough to be worth a special case in the type system, IMO. Maybe some syntactic sugar could be worthwhile, but not a magic type that behaves differently from other types (which is what Kotlin's ? is) - you need it to behave like a normal type so that you can write and reuse generic code. Arrow-kt can't implement functions that work with nullable values, and has to implement its own Option type instead.

> • Highly efficient translation to machine code. No boxing, no unnecessary branching in the unwrap/!! case.

Getting the semantics right is the important thing; it doesn't matter how fast the code runs if it's broken. It's still possible to compile a well-behaved option type into something unboxed in the cases where it can be represented that way (look at what Rust does, where the option is "packed" if 0 is not a valid value for the inner type, but still does the right thing for Option>, Option and so on).

Re: New Features in Java 14

#176
post #58

Earlier quoted context omitted.

I have no faith that Java will ever solve the problem after their bungled introduction of the Option type. Step 1 to migrating away from null would be to introduce a working Option type - one that could contain any valid Java value (which includes null for the time being) and where chaining behaviour worked the way you expect (i.e. that doesn't violate the monad laws, even when nulls are being thrown around). People…

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 key to null. That way you don't have to rewrite the whole world to use optionals before you start getting the benefit: even if the code that's populating the map doesn't know about optional and is still using null, you've still solved your problem.

Instead, with the implementation that we got in Java, if you tried to write this Map.getOption then if your map was ever used with old code that used nulls then it would break. So there's no way to ever start migrating to using options.

There are other problems with null, but they mostly boil down to the same issue: different code uses null to represent two different things, and so gets confused about what it means. (The other problem is that you can't look at a value and know that it can't be null, but optional definitely can't solve that until the whole ecosystem migrates to it).

Re: New Features in Java 14

#177
post #58

Earlier quoted context omitted.

I have no faith that Java will ever solve the problem after their bungled introduction of the Option type. Step 1 to migrating away from null would be to introduce a working Option type - one that could contain any valid Java value (which includes null for the time being) and where chaining behaviour worked the way you expect (i.e. that doesn't violate the monad laws, even when nulls are being thrown around). People…

From your blog (5.5 years using scala) it seems that null is a problem in scala: Scala avoids the biggest pitfall of multiple inheritance elegantly, by only allowing one parent to have a constructor; classes may only be the first parent, and traits can't have constructors that take arguments. Unfortunately this doesn't mean they don't need to be initialized; in particular, vals in a mixed-in trait will be null if you…

Null is not the problem there, null is the symptom. You see exactly the same problem if the val is a primitive type (which can't ever be null): if you access an Int from a mixed-in trait in an earlier constructor, that Int will be 0. This is a real issue, and one where I think Java has actually made the better design choice (interfaces may contain method implementations and constants but not fields - of course they had the benefit of Scala's experience when making that decision), but it's not about null.

Re: New Features in Java 14

#178
post #73

Earlier quoted context omitted.

Looks like it's doing annotation processing at compile time? The trouble with that is that you end up with "magic" code like calling methods that don't appear to exist, and in order to be able to work on the serialisation itself (e.g. to add a new format) you have to understand the "magic", because there isn't a good intermediate abstraction. The great advantage of Shapeless is that all the "magic" is in the library…

It's not annotation processing, it's a compiler plugin with IDE support. So pretty deeply integrated. It avoids some of those issues. The kotlinx.serialisation design is pretty nice. It's basically what you describe. The compiler generates generic code that can call into a variety of "codecs" but they don't have to actually be serialisation specific. So there are codecs for JSON, protobufs, CBOR etc but you can also…

> It's basically what you describe. The compiler generates generic code that can call into a variety of "codecs" but they don't have to actually be serialisation specific. So there are codecs for JSON, protobufs, CBOR etc but you can also do arbitrary object graph transformations with the framework. A deep clone being a simple hello-world type example.

So what does the value that gets passed into your codec look like? What makes Shapeless tick is that it can represent records generically at the type level; records will have a type like

    type Book = 'author ->> String :: 'title ->> String :: HNil
that you can actually break down and do meaningful operations on (e.g. you could run it through a function that counts the lengths of strings and get something of type 'author ->> Int :: 'title ->> Int :: HNil, in a fully type-safe way). I'd be impressed if someone managed to encode those kinds of types into Kotlin - e.g. I don't think Kotlin has singleton types, so being able to compare field names at the type level is probably impossible?

Re: New Features in Java 14

#179
post #61

Earlier quoted context omitted.

When you write unwrap(), you're handling them - by forcing a panic, but it's still a choice that you make.

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 type! - so even if it's applied incorrectly in advance, that still requires some conscious consideration.

This is not at all the same as forgetting an "else" - or, far more often, forgetting the "if" altogether.

Re: New Features in Java 14

#180

How do I propose a language change? One thing I'd really like to see is optional type declarations in Lambdas to bulletproof them. Take this simple Lambda List names = new ArrayList (); names.stream().filter(String name -> "Bob Vance".equals(name)).findFirst().get(); By adding the String type declaration, a whole host of bugs in really complicated Lambdas can be eliminated and found easier when the original types and…

Can't you do .filter((String name) -> "Bob Vance".equals(name)) already?

Oddly enough I'm having trouble finding references around this, even though it most definitely compiles.
Post reply on HN