News for hackers. Stuff that matters.
Re:New Features in Java 14 by cryptos on Tuesday March 03, 2020 @04:53PM (#22479083)
Java is quite far away from finally solving NullPointerException issues. Kotlin, C# or TypeScript with their compile time null checks solved it mostly. Common to these three languages is that they need null to be interoperable with older language versions (C#) or with related languages (Java, JavaScript). Languages like Rust that don't even know null (or nil as in Go), have finally solved the problem.
Re:New Features in Java 14 by baddox on Tuesday March 03, 2020 @06:33PM (#22479784)
> Languages like Rust that don't even know null (or nil as in Go), have finally solved the problem.

I wouldn't quite phrase it that way, since it's nothing new. OCaml from the 1990s has no null value (you need to represent potentially missing values with Option). I suspect there are older examples than that.

Re:New Features in Java 14 by swsieber on Wednesday March 04, 2020 @12:09AM (#22481358)
I would tentatively phrase it like that. It's not that rust is original in that regard, but instead effective though actually being adopted.
Re:New Features in Java 14 by justinhj on Tuesday March 03, 2020 @05:16PM (#22479252)
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.
Re:New Features in Java 14 by sk5t on Tuesday March 03, 2020 @08:03PM (#22480311)
Build plugins - do you mean wartremover or something else?
Re:New Features in Java 14 by justinhj on Thursday March 05, 2020 @01:03PM (#22496165)
Yes Wartremover, Scalastyle, Codacy, Scalazzi all help with this to varying degrees
Re:New Features in Java 14 by yayajacky on Tuesday March 03, 2020 @05:16PM (#22479254)
You hit it right on the nail. I love how the null type being defined away from function signature in TS. It's not entirely bug free but it gets pretty far!
Re:New Features in Java 14 by lmm on Tuesday March 03, 2020 @09:42PM (#22480775)
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 languages that have solved the problem told the Java folks about these issues, and were ignored, with the result that it's impossible to migrate an existing Java codebase to use Option, and I can't imagine the Java community having the appetite to introduce a non-broken Option that would allow moving off null.
Re:New Features in Java 14 by vbezhenar on Wednesday March 04, 2020 @04:47AM (#22482411)
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.
Re:New Features in Java 14 by lmm on Wednesday March 04, 2020 @08:22PM (#22490044)
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 by vbezhenar on Thursday March 05, 2020 @03:36AM (#22491917)
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 by lmm on Thursday March 05, 2020 @04:35AM (#22492194)
> 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 by manthideaal on Wednesday March 04, 2020 @04:58AM (#22482472)
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 try to access them in an earlier constructor.[2] As with any null, in the worst cases you may not get an error until much later on.

Re:New Features in Java 14 by lmm on Wednesday March 04, 2020 @08:31PM (#22490096)
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 by pjmlp on Wednesday March 04, 2020 @01:48AM (#22481707)
You can get those compile time checks with PMD. It plugs into all major Java IDEs and build tools.
Re:New Features in Java 14 by rafaelvasco on Wednesday March 04, 2020 @07:42AM (#22483226)
Well, what I meant is that they're solving the unhelpful messages :) The root of the problem is still there. Only languages without Null and everything that entails have truly solved the problem.
Re:New Features in Java 14 by jfkebwjsbx on Wednesday March 04, 2020 @03:34AM (#22482089)
C++ has had non-null references for decades.
Re:New Features in Java 14 by rakoo on Tuesday March 03, 2020 @05:32PM (#22479365)
> Languages like Rust that don't even know null (or nil as in Go), have finally solved the problem.

I'm in no way a Rust expert, but I see a lot of code with Optionals, something like

    match sth {
      Some(v) => do_something
      None => nothing_to_do
    }
This looks awfully a lot like

    if (something == null) {
       nothing_to_do
    } else {
       do_something
    }
It might look more pleasant, but it doesn't "solve" anything, only shifts it in a different place.

Go is in the middle, because structs have no null value, only a zero value; the only thing that can be nil are pointers which I personally feel should used as little as possible.

Re:New Features in Java 14 by Sharlin on Tuesday March 03, 2020 @05:46PM (#22479462)
In Java you're passed a reference to an object. Might it be null? Can it be null? Who knows! Mostly you're just going to ignore the possibility and hope for the best.

In Rust you're passed a reference to an object. Can it be null? No, it simply can't! There does not exist a magic "null" value for references. To represent the possible absence of a value, you explicitly encode it into the type system by using `Option<T>`.

Re:New Features in Java 14 by hcarvalhoalves on Tuesday March 03, 2020 @10:39PM (#22481021)
Just changed from having a bottom null type for all types to everything being a boxed Option type. It’s equivalent.

The actual difference is the reliance on pattern matching and the compiler enforcing coverage on those languages.

Re:New Features in Java 14 by LessDmesg on Wednesday March 04, 2020 @02:06AM (#22481776)
Option types don't have to be boxed and are specifically optimized in Rust and, if I remember correctly, in Haskell. The Nothing is represented much like a null pointer, i.e. with a special value that can't be dereferenced.
Re:New Features in Java 14 by tome on Wednesday March 04, 2020 @03:37AM (#22482104)
Not in Haskell, FYI. Maybes are boxed.
Re:New Features in Java 14 by james_s_tayler on Wednesday March 04, 2020 @03:21AM (#22482038)
In Java the Option of T type blows up the same way a NullPointerException does if you try to use the Option's value when it contains none.

I agree. In Java at least the semantics are practically identical.

I can't comment on Rust. I suspect it does a slightly better job.

Crystal is another language where there is no null. It's quite cool.

Re:New Features in Java 14 by steveklabnik on Wednesday March 04, 2020 @08:22AM (#22483500)
Rust refuses to compile, because an Option<T> type is a different type than T, so if you try to use it like one, you get a type error.
Re:New Features in Java 14 by swsieber on Wednesday March 04, 2020 @10:37AM (#22484619)
Java would also refuse to compile using an Optional<T> where T is expected.

Java and Rust are practically the same regarding the differences between Optional<T> and T (java), and Option<T> and T (rust). Optional<String> in Java has the `.get()` method which corresponds to the `.unwrap()` method in Rust. And in both are different different types than String in their respective languages.

But in Java you can have an Optional<String> that's null, not just empty. So that's three states - null, wrapping null, or wrapping a value.

I'd say the big difference is that in Rust you can have places that refuse nulls (e.g. using T instead of Option<T>), so you have well defined points of control/checking. That, combined with the difficulty in recovering from a panic (the equivalent of a null pointer exception when trying to unwrap a value that's missing) and the Result type, are Rusts real strength wrt. missing values.

Re:New Features in Java 14 by steveklabnik on Wednesday March 04, 2020 @11:42AM (#22485280)
I think we are saying the same thing, from slightly different perspectives. That Option can be nullable means that it can be used where it is not actually that type, without a type error, is what I’m saying.
Re:New Features in Java 14 by Sharlin on Wednesday March 04, 2020 @02:25AM (#22481840)
Huh, what? You don’t need or want most values to be potentially absent.
Re:New Features in Java 14 by thu2111 on Wednesday March 04, 2020 @05:29AM (#22482622)
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 about heavyweight syntax and the need for the compiler to successfully scalarise: using language integration around standard null pointers means the CPU spends no time on checking the 'maybe' branch. If the type system wasn't violated and a value is present, it's used immediately without any additional instructions or code bloat. If it's not then that will trigger a page fault at some point in the CPU pipeline and transfer control to an exception handler. If the type system indicates nullability and you need to actually do more than just unwrap it, then you have to take a branch of course but it's fully inlined and cheap.

Re:New Features in Java 14 by strbean on Wednesday March 04, 2020 @04:14PM (#22488211)
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.
Re:New Features in Java 14 by thu2111 on Thursday March 05, 2020 @01:09PM (#22496242)
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 by pjmlp on Wednesday March 04, 2020 @01:50AM (#22481712)
Integrate PMD and enable its errors as broken builds, done.
Re:New Features in Java 14 by rakoo on Wednesday March 04, 2020 @04:59AM (#22482479)
I know what an Optional is, the problem is that this pattern of wrapping stuff in Optionals seems to appear a lot, which means that in practice you have to do this little dance like you would in Java or, as others pointed out, try your luck with unwrap() and hope it goes well. In practice, it doesn't make coding much different.
Re:New Features in Java 14 by sgift on Wednesday March 04, 2020 @05:50AM (#22482707)
You seem to forget all the cases in Java where you didn't expect null to happen, but for some reason something was null and you get a NPE. Sure, if you check all values for null already the difference to now is not very big, but no one I know does this. Everyone has some intuition whether something "can" be null or not. Rust (and other languages without null) formalize the notion of "this cannot be null", so you don't have to depend on your intuition anymore - and cannot be wrong about it.

Regarding unwrap: If you tell the compiler "I know what I'm doing" and you don't know what you are doing then no one can help you. It's the same as putting casts everywhere when the compiler yells at you about incompatible types: If you lie to the compiler it will do your bidding, but your code will run into errors at runtime that you could have prevented at compile time. Again: No one can help you here.

Re:New Features in Java 14 by fidelramos on Tuesday March 03, 2020 @05:38PM (#22479405)
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.
Re:New Features in Java 14 by reificator on Tuesday March 03, 2020 @07:36PM (#22480176)
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't have a secret (not)T that invisibly breaks everything.

Re:New Features in Java 14 by imtringued on Tuesday March 03, 2020 @08:45PM (#22480497)
> 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.

Are you sure? Each line of Java or Javascript can be equivalent to multiple `unwrap()` calls. You can't see them because the compiler is generating ([0]) them but they are there and there are many hundreds of thousands (or maybe even millions including dependencies) of them in most Java projects.

Here is an example: company.board.members.size() is equivalent to company.unwrap("NPE).board.unwrap("NPE).members.unwrap("NPE).size() and every single line in Java is like that. You can't opt out. You can't tell your coworkers to stop using "unwrap" during code reviews. The entire language forces you to do this in every single line that involves a reference.

[0] Well, it's actually just trapping the 0 address but it's equivalent.

Re:New Features in Java 14 by reificator on Tuesday March 03, 2020 @10:11PM (#22480898)
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 in Rust you cannot leave null/None values unhandled. This is false because `unwrap()` exists and more importantly is in fairly common use.

The distinction is not whether you can (at your own peril of course) assume a value is not null. Rust lets you do that.

As you point out however, it does force you to be more explicit. Why is that? It's because the concept of `None` is not hidden from the type system.

The reason that your Java examples work that way is not because `unwrap()` is implicit, it's because the type system doesn't know about nulls in the first place.

Re:New Features in Java 14 by int_19h on Tuesday March 03, 2020 @10:21PM (#22480935)
When you write unwrap(), you're handling them - by forcing a panic, but it's still a choice that you make.
Re:New Features in Java 14 by reificator on Wednesday March 04, 2020 @07:24PM (#22489728)
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 by int_19h on Wednesday March 04, 2020 @10:06PM (#22490586)
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 by reificator on Thursday March 05, 2020 @01:13PM (#22496283)
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 by steveklabnik on Wednesday March 04, 2020 @07:32PM (#22489768)
> 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 by reificator on Wednesday March 04, 2020 @07:37PM (#22489795)
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 by crooked-v on Tuesday March 03, 2020 @08:00PM (#22480295)
Typescript is another one where null and undefined are unique singleton types, which are encompassed under the catch-all `any` type but, if strictness is turned on, are rejected by any other type matching.

    doThingA(param: any) // you can pass anything including null and undefined
    doThingB(param: object | number | string | boolean | bigint | symbol) // you can pass anything except null and undefined
Re:New Features in Java 14 by strbean on Wednesday March 04, 2020 @04:31PM (#22488370)
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.

Re:New Features in Java 14 by reificator on Wednesday March 04, 2020 @07:21PM (#22489700)
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 by strbean on Monday March 09, 2020 @05:28PM (#22530023)
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 by sgift on Wednesday March 04, 2020 @05:52AM (#22482716)
If you don't care about the else case you can use if let: https://doc.rust-lang.org/rust-by-example/flow_control/if_le...
Re:New Features in Java 14 by bcrosby95 on Tuesday March 03, 2020 @05:35PM (#22479385)
It solves it by making sure you handle it at compile time.

In Java you tend not to know where or when null checks have or will happen. So you tend to sprinkle null checks all over your code just incase someone somewhere forgot to check.

Re:New Features in Java 14 by hawk_ on Tuesday March 03, 2020 @05:39PM (#22479415)
The difference is that the choice of Optional is deliberate in the parts of code where None is a valid value. In java you have no first class way to indicate that null isn't an expected value for some variable and so type checker can't block it. In rust type checker wont let None slip in accidentally if you don't use Optional.
Re:New Features in Java 14 by tmpz22 on Tuesday March 03, 2020 @06:05PM (#22479594)
I can't speak for Rust, but in Go accessing properties of nil objects and dealing with 0-values for non-pointer values can cause bugs in certain contexts where you "let your guard down".

    func getFoo() (*Foo, error)

    func main(){
        foo, err := getFoo()
        if err != nil {
            // be an adult and handle your error
        }

        foo.Work()
        // panic because whoever implemented getFoo returned a nil object
    }
Also worth noting dealing with booleans in JSON is wonky because boolean values default to false, even if that json property wasn't set over the wire. Thus you end up unmarshaling to a pointer to a boolean, which now requires nil guards throughout your codebase when working with that unmarshaled object...
Re:New Features in Java 14 by steveklabnik on Tuesday March 03, 2020 @06:34PM (#22479790)
Rust does not have nil objects nor zero values.

The equivalent rust code would fail to compile.

Re:New Features in Java 14 by erik_seaberg on Tuesday March 03, 2020 @07:02PM (#22479981)
Go also has https://golang.org/doc/faq#nil_error, so interface != nil doesn't ensure it's safe to call any of its methods.
Re:New Features in Java 14 by reificator on Tuesday March 03, 2020 @07:32PM (#22480156)
That's a huge improvement.

It means that you've told the type system what it needs to support you.

If your function tells the type system you need a reference to a type, you get a reference to that type. There's no hidden timebomb in there where you might get something that supposedly is that type but can't be treated as that type.

This lets you write your functions to accept nulls where appropriate, and require some form of unwrapping at the call site otherwise. It tells you when you've missed something and it lets you refactor without having to constantly repeat all of your checks, once you know something is valid the type system reflects that for you.

In short if you have a T in rust, you know that it's not secretly a (not)T that is implicitly allowed anywhere a T can be.

Re:New Features in Java 14 by imtringued on Tuesday March 03, 2020 @08:39PM (#22480468)
>It might look more pleasant, but it doesn't "solve" anything, only shifts it in a different place.

It shifts it right into your face. You're forced to do something instead of pretending that everything could be potentially null. Since the only places where you can actually encounter "null" are documented you are no longer wasting your brain cells on the happy path where you are guaranteed to never see a null value when you don't expect it. Instead you can free up all that cognitive capacity to actually write correct code that handles null values.

Re:New Features in Java 14 by lmm on Tuesday March 03, 2020 @09:26PM (#22480698)
For the case where something really could be absent, you're right; it's the same amount of code. The difference is that in a language with null you have to write that code for every single function parameter, whereas in Rust you can have required parameters that are actually required and only need to check the genuinely optional cases (which is what, maybe 5% of the time?). Make invalid states unrepresentable.
Re:New Features in Java 14 by chii on Tuesday March 03, 2020 @06:26PM (#22479744)
Using the `match` method, you can guarantee that in the `some()` branch, v is not null, and will never be null.

In the `if == null` method, the `something` reference is null, but if you have functions that also reference `something` down the line, you're going to have to check it again for null-ness.

Re:New Features in Java 14 by steveklabnik on Tuesday March 03, 2020 @06:33PM (#22479783)
This specific pattern can be re-written as

  sth.map(|v| do_something);
incidentally.
Re:New Features in Java 14 by benibela on Tuesday March 03, 2020 @06:17PM (#22479670)
And you can write sth.unwrap() in Rust, and then it panics when it is null.

Kotlin solves it much better. sth?.do_something() ?: nothing_to_do

Re:New Features in Java 14 by aw1621107 on Tuesday March 03, 2020 @07:02PM (#22479982)
Rust does in fact have a ? operator [0], but it works slightly differently than Kotlin's in that it returns early if a None/Result<Err> is encountered instead of just resolving to that None/Result<Err>. If that isn't what you want, then Option::map() is a fine substitute.

[0]: https://doc.rust-lang.org/edition-guide/rust-2018/error-hand...

Re:New Features in Java 14 by benibela on Wednesday March 04, 2020 @05:04PM (#22488653)
But there is still a function that panics.

Java has solved memory safety. Now the task is to make sure that code that can panic will not compile

Re:New Features in Java 14 by aw1621107 on Wednesday March 04, 2020 @05:38PM (#22488930)
The function that can panic still exists, but the ? operator itself won't invoke a panic. Sort of like how you can still get NullPointerExceptions in Kotlin using !!, but standard practice is to use a safer option.

Exception/panic-free code is fairly straightforward; you just need to have APIs return Option<_>/Result<_>/other error code equivalents to indicate failure. The problem with that is that it introduces some amount of friction that will probably make some programmers unhappy.

If you want to avoid returning Option<_>/Result<_>/other error code equivalents, you need some way to prove your inputs cannot trigger an invalid result, and that is a very difficult problem.

Re:New Features in Java 14 by lmm on Tuesday March 03, 2020 @09:46PM (#22480786)
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.
Re:New Features in Java 14 by thu2111 on Wednesday March 04, 2020 @05:36AM (#22482645)
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 efficient translation to machine code. No boxing, no unnecessary branching in the unwrap/!! case.

• Excellent interop with older code written in OOP languages that don't represent nulls in the type system.

• But that older code can be annotated with @NotNull and @Nullable to retrofit the information; within Java IntelliJ will statically analyse these and add warnings where an NPE/panic would occur, when such code is used by Kotlin the annotations cause the types to be correctly derived as nullable or non-null.

• The large wealth of libraries that want to explore object graphs continue to work without being distracted by option/maybe types (e.g. serialisation, UI binding)

• On the rare occasions where you do need to unwrap and you got it wrong, you now get an error message that breaks down the sub-expression where the null pointer occurred, so there's no incentive to break up long chains of dereferences just to get better debugging in case of failure.

That's a featureset around optionality that's hard to match.

Re:New Features in Java 14 by lmm on Wednesday March 04, 2020 @08:14PM (#22490001)
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<T>>, Option<Int> and so on).

Re:New Features in Java 14 by pix64 on Wednesday March 04, 2020 @12:10AM (#22481363)
Option<T> explicitly states the value may be none.