13 ms·
Java 8’s new Optional type doesn't solve anything
- w23j 11y agoTL;DR You can call `Optional.get()` to deliberately circumvent the safety mechanisms of Optional. The author apparently concludes that since it does not solve ALL error cases it does not solve ANY error cases...
- Cthulhu_ 11y agoThe problem is that you don't get guarantees that something is not null; you can still do Optional<T> myOptional = null. Second, you're not required to handle the not-present case. Third, if you attempt to get the value of an optional (using .get()) when it is not present, you get an (unchecked, so no requirement to catch) exception - basically replacing NullPointerException with NoSuchElementException. The only value Optional has over regular values is that the developer has to assume the value can be missing - but the same was true for nullable properties.
- w23j 11y agoAt least one of the values of Optional is to communicate in the API that a value can be missing. The article mentions that: A programmer looking at the code for the first time will know, just by looking at the return type, "Hey, this method may not return a record! I'll have to handle that scenario." Making this clear to users of an API is something that nullable properties can not do. The user has to deliberately ignore the fact that the value might be missing by calling `.get()`. This looks like a advantage to me, so to say that Option does not solve ANYTHING seems incorrect. It certainly does not solve EVERYTHING.
- malka 11y ago> A programmer looking at the code for the first time will know, just by looking at the return type, "Hey, this method may not return a record! I'll have to handle that scenario." Well, that's basically the same thing with any nullable return then. Wether I return T or Optional<T>, there might be no record. Even worse, when I return T, you only have 2 cases : I return something, or I return null. With optional, you have 3 cases to check : I returned Something, I returned Optional.of(null), or I returned null.
- organsnyder 11y agoYou should never have to check that the Optional itself is null. While that is allowed by the language, it is such an obvious error that static analysis tools could easily detect it.
- MBCook 11y agoThen it shouldn't be allowed by the language, and that's the core issue. Until the compiler enforces that Optionals aren't null they're not fit for most purposes.
- w23j 11y agoI am not sure I understand. I guess you are either saying (A) to treat every return type as possibly null or (B) to use your judgment when doing null checks of return types. In case of (A): Do you want to write null-checks for methods like String.toUpperCase() or for user.getLastName()? That would lead to a lot of bloated, dead code. Also do you want to write error handling for all these cases you know can never happen? In case of (B): NullPointerExceptions are most likely when the user of an API did not expect he might get a null value. For instance user.getDepartment -> null. "What? An employee does not have to have a department?!" In this case you force users of an API to guess if they might reive a null return value. And they might guess wrong, which either leads to dead code or NPEs. Using Optional as a return type makes the difference explicit.
- MereInterest 11y agoI would say that every return type that can be NULL should be checked for being NULL. In C++, this is possible, because you most functions are return-by-value or return-by-reference. This leaves only return-by-pointer that need to be explicitly checked. In Java, all functions that do not return primitives are return-by-pointer, and are therefore nullable. This, as you mentioned, makes it infeasible to apply null-checks on every function return.
- craigching 11y ago
- jcrites 11y ago> Optional<T> myOptional = null That hasn't been a problem for me in practice. It's pretty clear that a reference to Optional should never be null. It can be statically or dynamically checked with @Nonnull or a precondition. > but the same was true for nullable properties. It's inconvenient to have to treat everything as possibly null. It's a lot nicer to create the convention, within one's codebase, that references are always nonnull and only Optional are nullable.
- gurkendoktor 11y ago> That hasn't been a problem for me in practice. It has for me. Functions have multiple return points, some of them returning "null". Lead developer insists we use Optional<> to clarify that these functions can return null. People go over the function, replacing each instance of "return null" with "return Optional.empty()", but forget some instances. Now we have Optionals that are sometimes null.
- RHSeeger 11y agoBut that's a bug in the library (or code you're calling into), not a bug in how you're using it. That's the main difference in my opinion. Optional allows the code to say "I never intend to return null, only an Optional that may be nothing". In theory, a library/module/whatever that's been converted to use Optional should not have any calls that do return null. In theory, its no different than a C API that can return a size or -1 for failure. Sure, it could return -2 because the language allows it, but you shouldn't need to check for that in your code that uses it.
- jcrites 11y agoIf you are in the midst of an upgrade like this, then you might want to program defensively. In this case I would do that by applying annotations like FindBugs' @CheckForNull or @Nonnull or @Nullable. Across a trust boundary like an interface, it's possible to establish a convention like: every reference shall have one of those. You might be able to write a CheckStyle rule that verifies that every reference either has an annotation or is an Optional. Last but not least, assertions can be tremendously useful. Add Objects.requireNonNull() checks liberally, especially anywhere you pass a reference from one place to another without using it. By applying these techniques you can quickly create a "demilitarized zone" for null, allowing you to use Optional confidently on the other side. Errors are caught quickly and locally by analysis and assertions. In a large codebase it's not an all at once upgrade, unless you refactor checked by static analysis, but you can be confident in the parts you've upgraded.
- AlisdairO 11y agoRight, but the difference in reality is that developers don't check every reference to see if it's null. The difference between a raw reference and optional is that with optional the author of the interface has explicitly signalled 'you really ought to check this'. Optional provides the ability to work with better conventions. Sure, this doesn't live up to the actual guarantees provided by other languages, but that's not the same as being useless.
- pjmlp 11y agoYou can do it today, but that won't work in Java 10 with value types. Optional is planned to become a value type.
- nrinaudo 11y agoI disagree with some of your points. The fact that you can get a null instance of Optional is not Java specific - Scala has the same issue, for example. Saying that Optional does not sort any problem because there is no way to enforce it cannot be null is just wrong - it sorts plenty of problems, just not all of them (you didn't mention the case of an optional that contains null, which is unpleasant as well). You can indeed call .get - so can you in Scala (.get) or Haskell (fromJust) with exactly the same semantics. What do you propose for the case where you know that there is a value in there but can't make the type system aware of that fact (you've called isPresent beforehand)? pattern matching and fail in the empty case? How is that different from calling get? Is it because of the fact that the exception is unchecked? In that case, why not throw a more specific, checked exception through orElseGet? And if you know that there is data to be had, isn't that exactly why we have unchecked exceptions in the first place? You absolutely are required to handle the not-present case - you can't treat an Optional<T> an a T, and someone will need to decide what to do at some point. Either the caller (ie you return an Optional yourself after mapping into it) or you. There's a wide range of ways you can do that, one of which being "I want to fail if there is no data" - that's either .get if you don't need a checked exception or .orElseGet if you need something more constrained. You can also decide to use a default value, or o different code path entirely... Optional has issues - it can contain reference to a mutable variable, for exemple, or you might find yourself with a null optional or an optional that contains null. It's not perfect. It's also a lot better than the alternative, null, as it lets you communicate some of your constraints to the compiler and allow it to catch certain kinds of errors at compile-time rather than at runtime. Rather like the rest of the Java type system, in fact - it's far from perfect, it doesn't catch all type errors at compile time, but it's (arguably) better than a fully dynamic one.
- ralmeida 11y agoDefinitely. For me, the main use case of Optional is to provide a way for programmers to express the semantic fact that "there is no such object" without resorting to null. Doing this leads to checking if (obj == null) for dealing with the semantic case that the object is not present, but other kinds of failure may cause obj to be null, but should be treated differently (for being a lower-level issue, for example). So, Optional<T> is basically a way to differentiate between different types of nullity.
- tux3 11y agoStatic analysis is great, but excessive annotations are not fun. In my (admittedly limited) experience, people omit them, forget to update them, and then rely on the analyser to magically catch everything. Sure, library solutions like Optional can always be misused, but there's no silver bullet to negligence.
- jcrites 11y agoThe lack of pattern matching doesn't make it useless. The existence of Optional reminds the programmer to check whether the value is present, and the type system does enforce this; you can't accidentally treat an Optional as a reference of the same type. The type system does help us remember to handle things; it is a reminder enforced by the type system that's easy to examine during code review. Yes, you can write get() and risk an exception. So don't do that. I'm still glad get() is present because there are times when the human knows the value will always be present, but sometimes in a way that can't be encoded in the type system. Alternatively, sometimes an absent value is an error and get() is an acceptable way to check-and-throw. I agree with the suggestion that static analysis can be useful, though many users had that already with FindBugs or Fortify. If we're talking about annotations based analysis, then it only goes so far. Optional and streams provide useful new tools for documenting intentions from my perspective. Another reason I enjoy the type is because it makes it a little more reasonable to say that, at least in new code, all references are nonnull references by default, since they'd be Optional otherwise.
- jontro 11y agoExactly, it forces the programmer to think about whether something can be null or not and actually had a behavioural change in my java coding.
- pandler 11y ago> Exactly, it forces the programmer to think It's a curious feature, the way you've described it. I have virtually no experience with Java so I'm looking at this from a totally foreign perspective. The authors considers it an ineffective feature because you still have to think about null checks, whereas you consider it an effective feature because it forces you to think about the problem instead of ignoring it.
- Zardoz84 11y agoI remember that somebody try to defend Java because have references instead of pointers so not is necessary to be worried about null pointers .. Ja!
- AndrewDucker 11y agoI think the main use of Optional is in a codebase which doesn't _ever_ allow "null". If every method call either returns an actual object then you can get rid of null checks, and not bother doing any checks on method returns that don't return an Optional.
- electrum 11y agoThat is exactly how we use Optional.
- bakhy 11y agosome have already commented here that author maybe complains too much (e.g., calling .get() on an Option<T> is a deliberate move, meaning that the developer explicitly took on the risk of that exception. that's very different than implicitly assuming that a regular ref is not null, using it and getting bitten in the ass.). but this one really hurts: "The last flaw with Java's implementation is a bit ironic — It's possible for the optional reference itself to be null." ouch.
- Latty 11y agoThis is another off-base point, in my opinion. Sure, it's possible for it to be null, and that isn't great - but the vast majority of null problems come from the user assuming the interface won't give you a null. Something returning an Optional should never return null, so the ambiguity is resolved. Sure, it still could as a bug, but that's actually a pretty rare case. I don't see it being a real problem.
- bakhy 11y agothat makes sense. i think an important question here is - what does "return null" in a method which returns Optional<T> do? will it return a null Optional<T>, or will it return a non-null Optional<T> which is empty? sorry to rub it in, but Java needs value types. this whole issue, however maybe irrelevant, does not exist in C#.
- pjmlp 11y agoOptional is planned to become a value type in Java 10, so while the current situation is less than perfect I don't consider it a big problem.
- jkscm 11y agoUsing get() is just bad style and so is returning null where you could return Collections.emptyList(). Previous discussion on reddit: https://www.reddit.com/r/programming/comments/3pl7o0/java_8s_new_optional_type_is_worthless/ https://www.reddit.com/r/programming/comments/3pl7o0/java_8s... tl;dr: use map, orElseGet, orElse
- vbezhenar 11y agoWhy it's bad? If I'm sure that this optional contains value, I don't see why it's bad. May be I checked this value presence few lines above.
- serpix 11y agoIf you are certain optional has a value, don't use optional. Checking presence of value of an optional is an anti-pattern, the same as doing != null checks. You should treat Optional the same as a List type with size 1. You never check if a list is size 1 before doing map or filter.
- vbezhenar 11y agoI'm not always own code. Simple example: getCharsetOpt("UTF-8") There is no way this code will return None in this particular case. So any additional checks are unnecessary and make code less readable.
- louthy 11y agoI don't know who said it, and this is probably a paraphrase: "If it can't happen, it will". If a function says the result is optional, then it's optional. It's not not optional because you decided it can't ever fail.
- nrinaudo 11y agoI feel get is acceptable style if you actually want to fail when there is no data to be had. If you don't have a default value to provide, nor an alternate code path other than "sod this, I'm bailing", get is ok. Not quite as good as using a more specific exception through orElseGet, but not bad, exactly. Also, if you have just called isPresent (and assume your data to be immutable), then get is ok - the alternative being to manually throw something like new IllegalStateException("the impossible has happened!"), which is not that much more useful, and is a pain to have to write all the time when you know it will not get called.
- _Codemonkeyism 11y agoShameless self plug "Comparing Optionals and Null in Swift, Scala, Ceylon and Kotlin" http://codemonkeyism.com/comparing-optionals-and-null-in-swift-scala-ceylon-and-kotlin/ http://codemonkeyism.com/comparing-optionals-and-null-in-swi...
- aembleton 11y agoWhat is the `nice` language you refer to?
- _Codemonkeyism 11y agoThis is an old JVM language http://nice.sourceforge.net/ http://nice.sourceforge.net/ I've included nice as it had a different syntax for optionals (?Type instead of Type?) which I found interesting. I was interested in Nice back in the day.
- desdiv 11y agoFYI your Scala example doesn't work. Welcome to Scala version 2.11.6 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_45). scala> var h:Option[String] = "Hello".some <console>:7: error: value some is not a member of String var h:Option[String] = "Hello".some
- andrioni 11y agoThe author is using the scalaz syntax, you could substitute it for the "vanilla" syntax: var h: Option[String] = Option("Hello") or import scalaz (in case you have it in your classpath etc): import scalaz._, Scalaz._ var h: Option[String] = "Hello".some
- _Codemonkeyism 11y agoSorry, as the other comment mentioned this is Scalaz as it makes code IMHO a little more readable. The example was more about the h:Option[String] part.
- vorg 11y ago
- vbezhenar 11y agoI don't understand what's wrong with get() method. Swift has built-in null-safety and it has "!" operator. Kotlin has it. Even Haskell has fromJust function which does exactly the same. May be name "get()" is too short and innocent-looking.
- danieldk 11y agoPartial functions such as fromJust are generally frowned upon in the Haskell community. There was a relatively recent proposal to deprecate and then remove fromJust: https://mail.haskell.org/pipermail/libraries/2015-February/025010.html https://mail.haskell.org/pipermail/libraries/2015-February/0...
- aljones 11y agoThe equivalents are not celebrated in other languages.
- Kwastie 11y agoThe author is missing the point. The fact that Optional can result in a nullpointer doesn't mean you should use in the same manner as null-checks. You shouldn't replace: if(x == null) { y = x.doSomething(); } with if(optionalX.isPresent()) { y = x.doSomething(); } You should replace it with: y = Optional.ofNullable(x) .map(ClassX::doSomething) .orElse(null);
- danieldk 11y agoThe author is missing the point. Is he? The point is that in Java you are still able to treat x unsafely, while languages with stronger typing do not. E.g. in Haskell, if a function returns a Maybe a, it will always be a Just a or Nothing value. Moreover, such languages allow you to make non-exhaustive matching against all constructors a compiler error. tl;dr: Haskell, Rust, et al. put the burden on the compiler. Java puts the burden to ensure safety on the programmer. (As can be witnessed in your snippet.)
- pron 11y agoAs of Java 8, Java has pluggable type systems[1], some of them are more advanced than what Haskell provides (like true intersection unit types), some effect types (locks etc.) and more. So Java puts the burden on some very advanced -- but optional -- type systems. [1]: http://types.cs.washington.edu/checker-framework/current/checker-framework-manual.html http://types.cs.washington.edu/checker-framework/current/che...
- cetra3 11y agoIt'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 appear at runtime.
- Retra 11y agoIt 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.
- ubertaco 11y agoAdding my voice to the din of people noting how far afield of the point the author is: You should almost never call .get(), except in cases where the code path does not allow an empty optional. Even so, calling .get() on an empty optional is better than handing nulls around. A null may -- by chance, really -- make it several lines down the code, so that the stack trace points you much later in the code than where the null originated. Calling .get() on an empty optional immediately throws a NoSuchElementException, pointing you directly to the line where the optional was empty where it shouldn't have been. Consider this code: User user = getUser(); // other stuff here // ... // ... String userSummary = formatUserSummary(user); // ... // ... where public String formatUserSummary(User user){ return "Franchise Location: " + user.getFranchise().getLocation().getName() + " Username: " + user.getUsername(); } An NPE occurs inside of formatUserSummary. Where did the null come from? Is the user's Franchise null? Maybe the Franchise's Location? Or is it the User that's null? If you instead took an Optional<User>, even if you just immediately unwrapped it with .get(), you'd at least get an error that unambiguously told you that it was the user that was missing.
- ucho 11y ago> Where did the null come from? A bit offtopic but SAP JVM puts that info in NPE error message[1], I don't know why others implementations don't, maybe it is incurring too large overhead? [1] it is something like "Attempted to call getLocation() on Franchise object returned from getFranchise() but it was null"
- Ygor 11y agoInteresting, first time I heard SAP has a JVM implementation. https://scn.sap.com/people/desiree.matas/blog/2011/12/07/sapjvm-overview https://scn.sap.com/people/desiree.matas/blog/2011/12/07/sap... Here is a presentation with some interesting points, wonder if anyone has any real-life experiences? https://www.youtube.com/watch?v=arryAs9lqfE https://www.youtube.com/watch?v=arryAs9lqfE
- kllrnohj 11y agoART on Android does this as well.
- pron 11y agoBrian Goetz's response: "They didn't solve the problem I thought they should have solved, so their solution is worthless." Thank you, internetz.[0] In any case, that's not what Java's optional is there for[1]. Solving the safety problem is the job of Java 8's pluggable type systems[2] that are both more powerful than the static-analysis tools listed in the article and had Oracle's official support (in the form of JSR-308). [0]: https://twitter.com/BrianGoetz/status/656860771196887040 https://twitter.com/BrianGoetz/status/656860771196887040 [1]: http://stackoverflow.com/a/26328555/750563 http://stackoverflow.com/a/26328555/750563 [2]: http://types.cs.washington.edu/checker-framework/current/checker-framework-manual.html http://types.cs.washington.edu/checker-framework/current/che...
- toolslive 11y agoI have the same feeling about boost's optional. It's a bandage on a wooden leg.
- stinos 11y agoBut is it really? Maybe I'm missing the point but it is a nice way to express that a function may or may not calculate something, no? At least it seems way better than returning bare pointers or pasing an argument by reference+returning bool, or returning a unique_ptr, or ...
- toolslive 11y agoIf you come from ML or Haskell and start using boost or Java's option, you actually feel ripped off. Some people claim it's a sort of documentation denoting 'intent', but I don't want documentation. I don't want options to infect the whole codebase, I just want to pattern match once and extract the value, and never have to check again for None or null. The problem in Java is the type system has references. X static use_it(X x){ ....} really has a signature something like this: use_it : X ref -> X ref no little library is going to fix that.
- gurkendoktor 11y agostd::string always is a value, boost::optional<std::string> isn't (similar to std::string, just a lot safer). The problem is that Java only has boost::optional<std::string>, which can be null, empty or a value.
- gurkendoktor 11y ago(Hacker News obviously wasn't made for writing about C pointers—the places where the text turns into italics and back where supposed to be asterisks.)
- kailuowang 11y agoImplementing a monad like structure without a monadic for loop syntax sugar tends to confuse people. It's hard to picture writing most operations as map or flatmap.
- spiralpolitik 11y agoWe've been using Optional<T> a lot in recent years (via Guava). It's useful, and has certainly reduced the number of NPE we've had slip through as it forces the developer to consider nullability up front. Looking forward to migrating to the Java 8 version when we upgrade to that JDK. One addition that would be useful would be some syntactical sugar to reduce the verbosity of using Optional<T>. But otherwise I'm happy and if you combine with @Nonnull and @Nullable annotations you get the best of both worlds.
- matteotom 11y agoI don't program much Java, but how expensive are exceptions? Wouldn't it make more sense to expect functions that could return null to instead throw a checked exception if something goes wrong? eg public dbResult doDatabaseThing(stuff) throws DatabaseException So if you do result = doDatabaseThing(stuff) the compiler will require you to do something about the DatabaseException. It seems to me that the point of, for example, Option and Result in Rust is to avoid the whole checked exception mess while still passing useful information about things that go wrong. But, given the problems pointed out in this article (lack of pattern matching and algebraic data types mostly), checked exceptions might be a more correct way to do it in Java.
- tel 11y agoAnd of course checked exceptions (wrapped in a try block) are "just" the nomadic effect of the option (or "result") type.
- alkonaut 11y agoYes. In this case the No-result means that the database query was successful, but no record was found. A connection error etc. should almost certainly still be thrown as an exception in Java. Without exceptions you would have to return a value that could discriminate between all 3 possible outcomes: nothing, error, result. In Rust this is the `Result<T, E>` struct.
- matteotom 11y agoIt that case, wouldn't it be better to return something other that `null` for no-result (an empty iterator? an empty list?)? That might be where Optional comes in, but I'm still not sure why a new language feature is needed for that.
- jryan49 11y agoI thought Optional was mostly for the steam API, and not just general usage?
- jryan49 11y agoAlso, despite it not being "standard" @NotNull, and @Nullable have worked really well for me so far. And I don't think Optional was meant to replace them.
- jrockway 11y agoI've only used the Guava version of Optional, which appears to have a slightly different API than Java 8's. (You can tell there's a Java 8 committee, that's for sure.) The biggest problem I found in applying Optional is that Optional is very much a Haskell-y concept to me, and Java programmers and Haskell programmers don't really overlap much. Therefore, to me, Optional is just a functor like a list or a set. So doing Optional.asSet() and iterating over the result is, to me, the correct way way of handling an optional value. If there's something in there, the loop runs once. If there's not anything in there, the loop runs zero times. This is exactly like "fmap" in Haskell: Prelude Data.Functor> fmap (+1) $ Just 42 Just 43 Prelude Data.Functor> fmap (+1) $ Nothing Nothing (Except that Haskell automatically preserves the type safety, whereas you have to re-wrap the value if you're using Java. Functional programming in Java never works, and this where the Optional idea starts to go wrong.) But I got "I don't really understand this" in code reviews every time I did that; the Java way is to check if it's set, then do a type-unsafe unboxing. Thus, like the article said, completely defeating the purpose of the Optional type. That said, it's pretty rare to need exactly 0 or 1 of something. If you're doing a database query, you can probably make the API return a set of rows. Then it's natural to loop over the results and nobody raises their eyebrows.
- tel 11y ago> That said, it's pretty rare to need exactly 0 or 1 of something. That's interesting and sort of hard to agree with. I think uniqueness is very often desirable and very often paired with a lack of certainty about existence. "Does a user with this identity exist?" certain is handled properly as a 0-or-1 question, e.g..
- jrockway 11y agoIs your method "getUserIfItExists(username)" or "doesUserExist(username)"?
- BorgHunter 11y agoIt'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): String = if(userDao.doesUserExist(username)) match { "Hello, " + userDao.get(username).getFullName } else { "Not logged in" } For one thing, the first function probably only makes one database call, while the second (absent caching) makes two. Secondly, the second carries with it the (unlikely) possibility that the user is deleted between your DAO calls. Thirdly, I would argue that the first function is easier to read.
- mbfg 11y agoAll of these problems seem trivial to me. The problem with Optional is that it isn't baked into the API, nor can it ever be, so any use of Optional is after the fact, applied only by the application, which means you need to wrap api calls in Optionals manually, which is something that gets real old, real quick.
- gurkendoktor 11y agoWe tried to use Optional<> instead of returning null. Accidentally returning null from methods returning Optional<> is something that actually happens, especially when migrating existing code. Of course you can solve that with @Nonnull annotations, but then why use Optional in the first place? The other problem is that the Optional<> interface is clunky. There is ifPresent(), but no ifAbsent(). The stream syntax is incompatible with the rest of the Java world, in the same way that List<T>#toArray has always been ridiculous. And if you use ifPresent(), you have to live with the fact that you cannot return from Java lambdas, and you cannot change any variables or even use non-final variables. I want to scratch my eyes out when I see people allocate one-element arrays on the heap just to work around Java's lambdas. I don't see the value of Optional<T> if you already have @Nullable.
- wcummings 11y ago>if you use ifPresent(), you have to live with the fact that you cannot return from Java lambdas That's what map/flatMap is for, ifPresent is really only useful for side-effects.
- loren_kuhn 11y agoWould be handy if I could filter out all medium.com entries from the front page for me. Never read anything mildly researched or balanced there...
- mariusmg 11y agoI really wished C# would support Nullable for reference types too. This + the new traversal operator (?. ) would be a great combo to get rid of NullReferenceExceptions. To me Optional<T> without pattern matching seems crap.
- mamcx 11y agoThis remind me of a old say: "What is worse than not given anything to somebody that need it? Give to him something broken".
- danking00 11y agoI think in this thread when we talk about "pattern matching" (which _is_ awesome) were caught up with two notions: pattern based destructuring of input and type enforced exhaustiveness checks. Java 8's Optional does give the latter: > maybeT.map(t -> ...).orElse(...) The author does make a good point that 'get' is unsafe. I think it was a necessary concession to team members who are learning how to program in this manner.
- greydius 11y agoI 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.
- cauterize 11y ago-Wall and hlint both don't warn about the use of undefined!! Am I off base thinking they should be screaming at the user?
- codygman 11y ago> 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. Null is encouraged and pervasive in Java, undefined is sometimes used as a placeholder and could be forgotten. You can't say that Maybe and Optional have the same amount of power because of this.
- aclissold 11y agoI've been using Swift for over a year now, which has had an Optional implementation from day one. I see a lot of people defending Java's implementation in this thread, can someone check my understanding? I did Java in a past life but am not super familiar with Java 8. In Swift, types are non-optional by default. You can never end up with a null, the compiler makes it impossible. Optionals are out of the way until you need them, and if you use them properly (i.e. avoid the .get() equivalent), it's still impossible to crash from a null. In Java 8, things can still contain null by default and you might not know about it, right? You can express that something is Optional in your API, but that's only marginally better than documentation, doesn't solve "unexpected nulls" whatsoever, and makes this only halfway to a solution and therefore broken entirely. Why not just use annotations? Are my assumptions and understanding correct?
- Lewton 11y agoI don't think anyone thinks that Optional as it is in Java right now is the perfect solution. The article seems to be making the case that Optional isn't an improvement of what came before, which is what people are having issues with.
- aclissold 11y agoAh. Right! "doesn't solve anything" is definitely not the case:)
- GhotiFish 11y agopublic Optional<Long> badIdea() { return null; } I think the fact that this compiles is all the argument necessary. What java needed was a ThisWillDefinatelyExist<Object>. Not the opposite, but java just can't do that.
- lukedegruchy 11y agoOptional (either JDK or Guava) is not perfect but is infinitely better than hand-checking for null. Among other things, it expresses the intent of the API writer that their method may or may not return an absent value and this is expressed via the type system. This is in stark contrast to using null as a primitive, which has no such transparency. For instance, there is no difference in Java's type system between a method that intends to always return a non-null String, and one that intends to return a null String under certain circumstances. Thus it is impossible for the user of the API to determine when to build conditional logic to check for null or when not to bother. In any case, the concept of null as a primitive is fundamentally broken. Due to Java's backward compatibility requirements, it's too late to resolve this in that language. However, newer languages don't need to make this mistake. However, there are "interoperability" requirements for new languages interfaces with legacy runtimes that tempt language designers to build escape hatches. These escape hatches exist in Swift, Kotlin, Rust, etc even though they're not recommended and their usage presents edge cases. Ceylon and Haskell seem to be the only two languages to get this completely right. Ceylon expresses optionality as the union between the present value type and null, which is an actual type separate from Object. An optional String is therefore a String|Null, or a String? Haskell accomplishes this with the Maybe type. All this to say that null should not be a primitive but should be banished to its own corner of the type system with clear compile-time semantics for dealing with the absence of values.
- nv-vn 11y agoThere are actually a lot of languages that do it in the same way as Ceylon does. However, Haskell goes a step further than most other languages by defining Maybe as a monad in the standard library.
- EvenThisAcronym 11y agoWhere did this myth that Option types are the "solution" to nullable references come from? That's got it perfectly backwards. The solution to nullable references is to remove them from the language; Option is just a means for languages that have already done this to encode nullability into the type of a value add necessary, as it should be. And people claiming that a language needs pattern matching or it doesn't solve the problem?! It makes me worry that those advocating these ideas are just part of the latest cargo cult and don't really understand the underlying principles or why these are good ideas in the first place.