News for hackers. Stuff that matters.
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.