Live data from Hacker News

Java 8’s new Optional type doesn't solve anything

medium.com

141–150 of 197 posts

Re: Java 8’s new Optional type doesn't solve anything

#141

Earlier quoted context omitted.

Care to explain why? Whatever unwrap provides can be done with a match+panic. Which is more explicit, but that's just splitting hairs -- unwrap is pretty explicit anyway.

I understand the anger but at the same time I don't. Overall unwrap() isn't good. Really it should be replaced by TODO WRITE ERROR HANDLING in 90% of its cases. That being said there are still good uses for it. The main _safe_ use for unwrap() I find is when dealing with an iterator of Results/Options (which seems to happen a lot). The pattern: .filter( |x| x.is_some() ) .map( |x| x.unwrap() ) Is safe, and I really d…

I'm not angry.

> Really it should be replaced by TODO WRITE ERROR HANDLING in 90% of its cases.

That's what the Rust community reads it as, mostly.

I've seen it occur very infrequently in libraries (aside from example/benchmark/test/mocking code, of course). When it does its usually for really out of whack errors like poisoned mutexes, crashed threads, etc (mind you, these are for unwrapping error values, not options, but it's almost the same thing). Or for cases where it's known to be valid due to invariants that can't be expressed in the normal way.

I did a quick grep of hyper, and the unwraps are almost all in "dev" code (tests/benchmarks/etc). The cases where they aren't are where there was an `is_some()` earlier (and due to some reasons it couldn't be restructured as a match, perhaps just because of rightward drift), or the "invariants" thing -- i.e. it often calls `.serialize_path().unwrap()`, which is OK, because hyper only ever deals with relative schemes (e.g. `http://` and `https://`, not `data:` or `mailto:` -- the latter two don't have paths), which is checked in the constructors, so this should NEVER panic. I didn't go through all the code, but in the main HTTP and HTTP2 code serialize_path was the only offender, which was one that was justified.

I see it more often in applications. In the following cases:

- Example applications in blog posts (because you want to explain something else, not spend too much time on error handling)

- Slightly less out of whack errors which are weird enough that they should close the app

- Normal errors which should close the app (e.g. "insufficient permissions" for a command line util, or a port-opening error on a network app). unwrap() prints out the error message so this is a very rudimentary form of error handling anyway.

- Laziness, or often with a TODO. Not too common.

So, it's mostly used in justifiable ways, and that's why it exists in the stdlib. It doesn't "wipe out" anything that the borrow checker provides (borrowchk and exhaustive match are two different things), and while it's a kludge if used often there are legitimate reasons to use it; enough reasons to have it in the stdlib.

> I really don't know a more eloquent method of handling these operations.

    .filter_map(|x| foo(x))

:)

(but yes, in general there are situations in which you know an Option is unwrappable, e.g. the serialize example above)

Re: Java 8’s new Optional type doesn't solve anything

#142
post #139

Earlier quoted context omitted.

>>Yes, you can write get() and risk an exception. So don't do that. >Yes, you can dereference a null pointer and risk an exception. So don't do that. Except these aren't at all the same. With a reference, you have no good way of telling whether your reference IS nullable. With Optional, it's ALWAYS optional. Therefore it is trivial to a) train developer habits to always check before fetch, and b) enforce an isPresent…

>Except these aren't at all the same. With a reference, you have no good way of telling whether your reference IS nullable. As the article mentions, we have annotations to do just that. >Therefore it is trivial to a) train developer habits to always check before fetch, and b) enforce an isPresent check with static checks. Again, if we're using static analysis to verify the correct use of Optional, why are we using op…

Much better than using static analysis is to have it in the type system:

https://kotlinlang.org/docs/reference/null-safety.html

It's simple:

val x: Foo = maybeGetSomeFoo() // Error: method returns Foo?

val x: Foo? = maybeGetSomeFoo()

x.sayHello() // Error: x may be null

x!!.sayHello() // OK, the !! method throws an exception if it's null

if (x != null) x.sayHello() // OK, flow sensitive typing means the test narrows the type

val h = x?.sayHello() // OK, ?. yields null if left hand side is null, otherwise evaluates right

val h = x?.sayHello() ?: return // OK, ?: runs right hand side only if left hand side is null

Re: Java 8’s new Optional type doesn't solve anything

#143
post #120
post #99

Earlier quoted context omitted.

In other languages that use Option types more natively, like Scala, anything that isn't optional is assumed to just not be null: The compiler doesn't guarantee it (it's not as if it can, we are dealing with a JVM here) but it works in practice. I've not seen a NullPointerException in years. Option has other advantages, like its compositional qualities (thanks to Option being a monad). So imagine the following code de…

> I've not seen a NullPointerException in years [in Scala] This sounds odd. Does your code never interface with Java libraries and frameworks? I envy you! It's all too easy to forget to wrap a suspect value from Java-land with an Option(..) . And cumbersome even if you do remember. And then, there's the code written by Scala novices who just love using nulls. Yes, yes, "code reviews", we all know they are always prac…

The Scala landscape is very, very quickly creating their own libraries for similar popular Java libraries/frameworks. It is entirely possible to create an application, web or otherwise, that uses no Java libraries at all (save for the sbt dependency tree).

As for "Scala novices who just love using nulls", if you're seeing that, then the coder in question missed day 1 of Scala training, which is always "if you are writing the word null, you are doing something wrong" (right up there with "if you are writing the word var, you are probably doing something wrong").

Re: Java 8’s new Optional type doesn't solve anything

#144

I love Haskell, but the existence of a bottom type throws all run time guarantees out the window. import Control.Monad ex1 = Just 1 :: Maybe Int ex2 = undefined :: Maybe Int inc = liftM (+1) main = do putStrLn . show $ inc ex1 putStrLn . show $ inc ex2 Yes, you should never use `undefined`. Now replace `undefined` with `null` and it becomes apparent that Maybe and Optional have exactly the same amount of power.

-Wall and hlint both don't warn about the use of undefined!! Am I off base thinking they should be screaming at the user?

Re: Java 8’s new Optional type doesn't solve anything

#145
post #89

Earlier quoted context omitted.

>Yes, you can write get() and risk an exception. So don't do that. Yes, you can dereference a null pointer and risk an exception. So don't do that. See where this is going? The problem with Java's optional is that it is by all appearances (in name and high-level description), a general purpose optional, albeit with a ton of gotchas that will result in people saying "Just don't do that." Java's optional is not a gener…

>>Yes, you can write get() and risk an exception. So don't do that. >Yes, you can dereference a null pointer and risk an exception. So don't do that. Except these aren't at all the same. With a reference, you have no good way of telling whether your reference IS nullable. With Optional, it's ALWAYS optional. Therefore it is trivial to a) train developer habits to always check before fetch, and b) enforce an isPresent…

> With a reference, you have no good way of telling whether your reference IS nullable.

You do, a reference is ALWAYS nullable/optional. Just because people might expect a certain reference never to be null does not change that. You could equally as well as semantically expect an Optional never to be "optional" (it is just a matter of perspective). People who are too lazy to check for null might be too lazy to check isPresent() and both will give you, unsurprisingly, an exception.

java.util.Optional is really just yet another layer added to support laziness in software developers. To put it bluntly, write better manuals/JavaDocs if necessary and, most importantly, read them.

Re: Java 8’s new Optional type doesn't solve anything

#146
post #137

Earlier quoted context omitted.

Java 8 Optional is useful (although the API could be better). If only FindBugs would warn about calling get() without checking isPresent() first. There's an open FindBugs ticket for this: http://sourceforge.net/p/findbugs/feature-requests/302/

That is the old bug tracker. An issue was submitted on the official tracker and immediately closed. See https://github.com/findbugsproject/findbugs/issues/56 for explanation.

[deleted]

Re: Java 8’s new Optional type doesn't solve anything

#147

Earlier quoted context omitted.

Is your method "getUserIfItExists(username)" or "doesUserExist(username)"?

It's pretty common to need to do something to your user object if it does exist. As a toy example, it's far better to have something like (using Scala syntax here): def getUserGreeting(userDao: UserDAO)(username: String): String = userDao.getOptionalUser(username) match { case Some(user) => "Hello, " + user.getFullName case None => "Not logged in" } than: def getUserGreeting(userDao: UserDAO)(username: String): Strin…

2nd version wouldn't compile (need to remove "match").

probably more idiomatic for the 1st version would be:

    userDao.getOptionalUser(username).map(u=>
      s"Hello, ${u.getFullName}"
    ).getOrElse("Not logged in")
i.e. string interpolate and map instead of match over Option.

Re: Java 8’s new Optional type doesn't solve anything

#148
post #139

Earlier quoted context omitted.

>>Yes, you can write get() and risk an exception. So don't do that. >Yes, you can dereference a null pointer and risk an exception. So don't do that. Except these aren't at all the same. With a reference, you have no good way of telling whether your reference IS nullable. With Optional, it's ALWAYS optional. Therefore it is trivial to a) train developer habits to always check before fetch, and b) enforce an isPresent…

>Except these aren't at all the same. With a reference, you have no good way of telling whether your reference IS nullable. As the article mentions, we have annotations to do just that. >Therefore it is trivial to a) train developer habits to always check before fetch, and b) enforce an isPresent check with static checks. Again, if we're using static analysis to verify the correct use of Optional, why are we using op…

>>Except these aren't at all the same. With a reference, you have no good way of telling whether your reference IS nullable.

>As the article mentions, we have annotations to do just that.

Your mileage may vary, but my experience with nullable/nonnull annotations is that because they are not used across the board, you are either left with a ton of false positives or a ton of false negatives. The fact that there hasn't really been a great standardization in the core language is probably evidence of that (yes, JSR305 exists, but the JDK doesn't enforce its constraints by default).

With Optional, it's a clean slate. You can simply say "a reference to an Optional shall never be null" and you could probably enable such an enforcement for an existing project. Of course it's not going to be 100% while it's still a normal reference type, but catching 99% of the cases is a really big improvement!

Re: Java 8’s new Optional type doesn't solve anything

#149
post #23

It's not a get out of jail free card no, but it's value isn't in preventing null pointers. The value of Optional is in providing intent. You also get map, filter, flatMap, orElse, orElseGet, ifPresent. These are all great ways of making your code more functional, and do more with less. I don't think annotations are the answer either, as you can't always rely on static analysis to prevent errors, a lot will still appe…

It does provide some type-level information, but if you're already writing documentation, the benefits are marginal. Add to that the fact that it really pollutes your interfaces, I would argue that it is almost always better to just pass a null and force people to check it, or read the documented guarantees.

Basically, just assume every Java type is wrapped in Optional implicitly. But by adding Optional (and using it in standard libraries) it's often a matter dealing with code that interfaces between the two styles -- another problem that didn't exist without Optional.

And even if you think Optional is worth the small gains, it's still a sad mimic of the Option types implemented in other languages.

Re: Java 8’s new Optional type doesn't solve anything

#150

Earlier quoted context omitted.

>>Yes, you can write get() and risk an exception. So don't do that. >Yes, you can dereference a null pointer and risk an exception. So don't do that. Except these aren't at all the same. With a reference, you have no good way of telling whether your reference IS nullable. With Optional, it's ALWAYS optional. Therefore it is trivial to a) train developer habits to always check before fetch, and b) enforce an isPresent…

> With a reference, you have no good way of telling whether your reference IS nullable. You do, a reference is ALWAYS nullable/optional. Just because people might expect a certain reference never to be null does not change that. You could equally as well as semantically expect an Optional never to be "optional" (it is just a matter of perspective). People who are too lazy to check for null might be too lazy to check…

If you ever have actual success getting developers to obey documented input/output constraints without actually enforcing them with a static or runtime check, you could probably become a highly-paid coach. But I'm skeptical. I've never seen it happen, and most good libraries I've used (e.g. Guava) always follow up preconditions with a runtime check. Statically enforceable pre/postconditions shouldn't even have to be documented because the signature is the documentation.

Good libraries allow their developers to be lazy.

Post reply on HN