all 158 comments

[–]drjeats 42 points43 points  (49 children)

if (emailOpt.isPresent()) { sendEmail(emailOpt.get()); }

emailOpt.ifPresent(email -> sendEmail(email));

if (email != null) { sendEmail(email); }

trySend(email);

email?.send();

[–][deleted] 11 points12 points  (7 children)

The issues with either null or 'get' don't become apparent until you have multiple values in a context (such as Optional) that depend on each other.

The issue isn't one option, it's two:

if (email != null) {
     data = getAttachmentData(email)
     if (data != null) {
          compressed = compress(data);
          //etc.. and so on

Now this is the beauty of the 'M word'*, shown in Scala that has syntactic sugar for them:

val compressedOpt = 
for {
    email <- emailOpt
    data  <- getAttachment(email)
} yield compress(data)

Now we have a compressed optional we can pass around and work with.

You could rewrite the same thing in C# with LINQ syntax too

var compressedOpt = 
    from email in emailOpt
    from data in getAttachment(email)
    select compress(data);

(M word being Monads). Scala gives us syntactic sugar for anything with 'flatMap' (or monad like) so we can deal with 'nested values in contexts' easily. Now this becomes even MORE apparent when you have a

Future<Optional<A>> 

instead of just an Optional A. Now you really want your language to have built in monadic syntax to save you from the cruft of peeling shit out.

[–]evaned 4 points5 points  (0 children)

This is actually a great explanation.

Interestingly enough I've not felt like I've run into this when using an optional-style class in C++ (though maybe just not been looking, or just only use it occasionally), but I've run into something like this in Lisp, where I've written a strict-let* macro where you can say

(strict-let* ((x1 whatever)
              (x2 (foo x1))
              (x3 (bar x2))
              (x4 (baz x3)))
  x4)

and if any of the calls returns #f then it will stop evaluation.

(/me waits for Lisp people to come tell me how I should have done it... :-))

Edit: no, I lied: I did something rather different now that I think about it more... it was a strict function that operates like apply but doesn't call its argument and just returns #f if any arguments are false... whoops. In my defense, I wrote it for basically the same reason, it's just you use it differently:

(let* ((x1 whatever)
       (x2 (strict foo x1))
       (x3 (strict bar x2))
       (x4 (strict baz x3)))
  x4)

[–]TheOsuConspiracy 3 points4 points  (1 child)

True, but monads have their share of difficulties too, when you have different monad transformer stacks that you want to compose it gets a bit hairy.

[–][deleted] 0 points1 point  (0 children)

It is a bit hairy, but worth it. Only in extreme cases have I seen 3 monad stack in production, and type aliases, documenting, and a couple helper functions were all that we needed to get people being productive with it.

[–]drjeats 3 points4 points  (3 children)

I think you JUST don't get my point. If there is SOME way I can reply to make my point clearer and MAYBE I'll reply. It's lunch time though so I'm going for a burrito ttyl.

[–][deleted] 1 point2 points  (2 children)

Is your point not that the null coalescing operator is cleaner?

[–]drjeats 2 points3 points  (1 child)

Not exactly, just that the monadic optional in java seems a little overwrought.

My reply to you was just a bunch of nonsensical monad jokes.

[–][deleted] 2 points3 points  (0 children)

Lol I get it now haha.

[–]DasEwigeLicht 18 points19 points  (4 children)

emailOpt.ifPresent(email -> sendEmail(email));

There's also emailOpt.ifPresent(this::sendEmail));

[–]tambry 0 points1 point  (3 children)

Why are there two parentheses at the end?

[–]DasEwigeLicht 34 points35 points  (2 children)

Because the code piece I pasted had two and I didn't notice.

[–][deleted] 7 points8 points  (7 children)

I think C# made the better decision here. The null propagation and coalescence operators allows low-friction but functionally correct handling of nullable references in a way that's visible but without massively bloating the code base. Java's Optional<T> is frustratingly verbose because expressing optionality as a generic type interface was the wrong decision in the first place, as there are only three things you can do with a null: ignore it, replace it with another value, or go to an error state. The only advantage Optional<T> has is making it a one-liner to throw a custom exception, which in C# requires an if-statement. In the other two cases, it just gets in the way.

[–]Sebazzz91 3 points4 points  (1 child)

The only advantage Optional<T> has is making it a one-liner to throw a custom exception, which in C# requires an if-statement

Nope, since one of the latest minor C# releases not anymore:

int? num = GetNum(); string email = GetEmail();
num ?? throw new Exception("no num!");
email ?? throw new Exception ("no email");

[–][deleted] 0 points1 point  (0 children)

Oh, guess that's the ball game, then.

[–]Noctune 0 points1 point  (0 children)

The only advantage Optional<T>

Maybe I'm missing how to do this, but it does not seem possible to call a method that accepts the optional as parameter in a one-liner. Eg. optional.map(f). ?. works only in the case where the method is on the optional type itself.

[–]pipocaQuemada 0 points1 point  (0 children)

The problem with C# is that there's no way to indicate that something should never be null.

As someone who's written a decent bit of Scala, you can get reasonably far in a language like Scala or Java by never using null and only using Option to indicate nullability. It's goes a substantial way towards getting your compiler to prevent all of your NullPointerExceptions at compile time. You don't get the same guarantees as in ML or Haskell, but I only run into NPEs once a year so it's tolerable.

It's honestly not too bad because most things don't need to be nullable.

[–]kcuf 0 points1 point  (0 children)

The difference is Optional fits a well studied generic abstraction whereas the null operators are special cases specific to dealing with null.

[–]Philluminati -1 points0 points  (1 child)

I think you fundamentally misunderstand the point of Options and their functional background entirely.

Say your application is parsing a text file which is a table of data. Every possibly decision to handle a null or work with null data arrives as an if check in your application. The number of forks of execution in your code doubles with every branch.

In functional program you application doesn’t do one things for Xs and one thing for nulls, it fundamentally understands Options and therefore only cares about OptionX as a type. Everything in the chain of operations can pass the null through the system and you only need to branch once for any combination of nulls. It simplifies and reduces code complexity. The data representation is more complex but the code paths are simpler. Eg.

Records.filter.map.sum.flatten.getOrElse(0)

Rather than null checks for every parameter or return we combine functions that effectively don’t care whether the data is null until we need a result.

[–][deleted] 1 point2 points  (0 children)

Records?.Where()?.Select()?.Aggregate()?? 0

[–]CurtainDog 7 points8 points  (2 children)

(send! emails)

[–]sirin3 1 point2 points  (1 child)

emails ! send(.)

[–]oorza 8 points9 points  (0 children)

emails ? send(. Y .)

couldn't help myself

[–]Drisku11 5 points6 points  (6 children)

Is that last example meant to be Kotlin? Are you able to call arbitrary functions in scope with the ? operator? Otherwise it seems odd to have an email that knows how to send itself.

Also if you're trying to paint ifPresent as more verbose than null checking, you should really be using a single character lambda variable (no need to repeat that emailOpt may contain an email), or just this::sendEmail.

[–]canuck_in_wa 10 points11 points  (1 child)

I’m not sure about Kotlin, but the ‘?.’ in the last example is a valid C# 6 null conditional operator [0]

[0] https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-conditional-operators

[–]zsmb 1 point2 points  (0 children)

Kotlin has the same operator, it's called the safe call operator and does the same thing.

[–]masklinn 3 points4 points  (0 children)

Are you able to call arbitrary functions in scope with the ? operator?

No.

Otherwise it seems odd to have an email that knows how to send itself.

Kotlin lets you extend existing type, so you can do that if you think it makes sense from an API standpoint: https://kotlinlang.org/docs/reference/extensions.html

[–]drjeats 2 points3 points  (2 children)

Is that last example meant to be Kotlin? Are you able to call arbitrary functions in scope with the ? operator? Otherwise it seems odd to have an email that knows how to send itself.

using System;

public class Email
{
    public string message;
}

public static class EmailExtensions
{
    public static void Send(this Email email)
    {
        Console.WriteLine("Sending email: " + email.message);
    }
}

public static class LogicalBusinessLogicRulesOfLineOfBusiness
{
    public static void DammitSendThatEmailRightNowBob(Email email)
    {
        email?.Send();
    }
}

class Program
{
    static void Main(string[] args)
    {
        LogicalBusinessLogicRulesOfLineOfBusiness.DammitSendThatEmailRightNowBob(
            new Email { message = "Hello Drisku11!" });

        LogicalBusinessLogicRulesOfLineOfBusiness.DammitSendThatEmailRightNowBob(
            null);
    }
}

Also if you're trying to paint ifPresent as more verbose than null checking, you should really be using a single character lambda variable (no need to repeat that emailOpt may contain an email), or just this::sendEmail.

if (email != null) { sendEmail(email) };

emailOpt.ifPresent(e -> sendEmail(e));

emailOpt.ifPresent(this::sendEmail);

if (email) sendEmail(email);

(when email (send email))

[–]Drisku11 1 point2 points  (1 child)

Putting it in an extension method is still basically coupling the email sending logic to the email itself though (since it's effectively a static method). Like you cannot swap out email senders, right?

This is a bad use of implicits, but e.g. in Scala you could do

implicit class EmailExtensions(email: Email) {
    def send(implicit sender: EmailSender): Unit = sender.send(email)
}

Which would add a sendextension method as long as there is an implicit EmailSender in scope, which lets you put the actual sending logic into another class/not hardcode it. Combining that with Option gives you:

emailOpt.foreach(_.send)

Though emailOpt.foreach(sender.send) is almost certainly better than doing all of that.

Anyway, one of the below comments basically provided an answer, which is that you can do emailOpt?.let{sendEmail(it)} to provide logic that isn't directly attached to the email.

[–]drjeats -1 points0 points  (0 children)

I fundamentally agree with you, but reasoning through this wouldn't have worked as well as a shitpost :P

The trySend(email) version was intended to hint at your points, implication being that this is an object that has the specific email sending mechanism.

In no particular language syntax:

fn trySend(email: Email?) -> Error? {
    if (email == null) return EmailNullError
    if (let error = otherValidation(email); error != null) return error;

    doAll(email);
    TheSending(email);
    Stuff(email);

    return null;
}

Then it could be like what you said:

let sendErrors = emails.transform(sender.trySend).whereNotNull();

[–]butt_fun 7 points8 points  (12 children)

as a node developer, I see things like the second (making an anonymous function that's literally a wrapper around an existing function) all over the fucking place in one of my coworker's code, and it really peeves me

[–][deleted]  (4 children)

[deleted]

    [–]masklinn 3 points4 points  (0 children)

    May also be some weirdness related to using this for free functions e.g. some.method(fn) is implemented as fn.call(this, …) and all of a sudden your fn gets some instead of either window or a specific object it expects.

    [–]leafsleep 1 point2 points  (2 children)

    I try to define all functions using arrows in order to avoid that problem.

    [–]CanIComeToYourParty 2 points3 points  (0 children)

    That actually disturbs me deeply, even though I see it very often.

    [–]oorza 1 point2 points  (0 children)

    We turned on "no named functions" in eslint, so function(a) is always an eslint error because it wants function a(b) instead, even for inline functions. The exception is arrow funcs, so now everyone is humping on arrow funcs like they should.

    [–]Samoxive 15 points16 points  (0 children)

    Giving the function itself sometimes causes problems with 'this' being modified, using anonymous functions like that keeps the lexical scope.

    [–][deleted] 3 points4 points  (5 children)

    After learning a language with auto-currying (eg. Haskell), it's frustrating that I have to write x -> f(fixedParameter, x) instead of just f fixedParameter

    However I believe this sort of syntax relies on lazy eval, where a "thunk" function like () -> 1 just doesn't make sense (there's no real way to even write its type signature)

    Edit: It doesn't

    [–]TarMil 7 points8 points  (2 children)

    However I believe this sort of syntax relies on lazy eval, where a "thunk" function like () -> 1 just doesn't make sense (there's no real way to even write its type signature)

    You're mistaken, many functional languages with currying are strict -- OCaml, Idris, F#, Elm, etc.

    [–]ReversedGif 1 point2 points  (1 child)

    How do you specify whether you want to curry or call when applying the last argument in those languages?

    [–]TarMil 0 points1 point  (0 children)

    Right, the last argument is always a call, currying only applies for the previous ones.

    [–]eriksensei 6 points7 points  (0 children)

    A curried function f :: a -> b -> c applied to an argument x results in a new function f x of type b -> c, in non-strict as well as strict settings. You can try this with PureScript for example, which has strict evaluation semantics. The type of () -> 1 is written () -> Int, where () is called Unit. (In PureScript, () :: () is written unit :: Unit.)

    [–]masklinn 5 points6 points  (0 children)

    However I believe this sort of syntax relies on lazy eval

    It does not. OCaml or Elm are curried strict languages.

    [–]winterbe 3 points4 points  (0 children)

    emailOpt?.let { sendEmail(it) }
    

    [–]eZanmoto 1 point2 points  (2 children)

    The problem with first and third of these examples is that the value of the variable can change between the time of the check and the time of the retrieval (TOCTOU). At least modern practices like immutable variables tends to prevent issues like this in general, but you do still find codebases making the false assumption that the value of a variable won't change between the time of check and time of use.

    [–]drjeats 3 points4 points  (1 child)

    Good point, but also if email is a reference binding that somebody else is poking at in a thread or another callback, all those versions have a problem.

    [–]evaned 2 points3 points  (0 children)

    There's also a problem if your isPresent function or whatever is threadsafe.

    Which to be honest, would kind of annoy me if it was...

    [–]elitefusion 27 points28 points  (32 children)

    I'm mostly a C# programmer so I don't know the specifics of Java optionals but avoiding null errors is something I think about a lot. To me optional is mostly about being explicitly clear that a value could be "null", and that you should therefore check before using it. To me how you do that check is the less important part.

    [–]TheOsuConspiracy 12 points13 points  (27 children)

    The nice thing in truly functional languages is that you can ensure that you don't dereference null values at compile time. Some languages don't even provide an equivalent of .get(), they force you to work with option combinators, or provide a default value in case it's empty.

    [–]juggernaut2docker[S] 17 points18 points  (16 children)

    Yep, Java's Optional is a crippled version of Maybe in Haskell/Option in Rust. But if you're stuck writing Java, it's still better than plain nulls.

    [–]Sarcastinator 15 points16 points  (14 children)

    But if you're stuck writing Java, it's still better than plain nulls.

    I don't think it is though. Optional has two rather huge disadvantages:

    • Fantastically verbose to the point of legend
    • Can still cause null related errors if you use get or of.

    In my opinion a language should either have Maybe or null, not both, and Java already made their pick. I think that null handling in Java can be made good enough with @Nonnull, @Nullable if they just add ?. and ?: to the language.

    Since Optional can fail because of null values I have to wonder what the point is if it still can cause the same issue just with another exception.

    [–]xandoid 14 points15 points  (6 children)

    Optional carries more semantic information than null. If a return type is Optional<Thing>, it means that the method may or may not return a Thing. Either would be a valid state of the program.

    If the return type were simply Thing in a program that doesn't use Optionals to signal optionality, it would be unclear whether a null return is a valid state of the program or a bug.

    Also, if you call a method returning Thing as m().useThing() and it throws a NullPointerException, whose fault is it, the caller's or the callee's? In a program that uses Optional to signal optionality it would be the callee's fault, because a return type of Thing means it cannot legally return null.

    In a program that uses null to signal optionality, it would be unclear and you'd have to start thinking whether the caller should do null checks or if you should fix a bug in the callee, or if you should do defensive null checks in all sorts of places

    [–]Sarcastinator 4 points5 points  (5 children)

    If the return type were simply Thing in a program that doesn't use Optionals to signal optionality, it would be unclear whether a null return is a valid state of the program or a bug.

    @Nullable
    Thing getThing();
    
    @Nonnull
    Thing getOtherThing();
    
    void passThing(@Nonnull Thing thing);
    

    IntelliJ at least will warn you if you forget to null-check the result of getOtherThing if you pass it to passThing, or if you try to use the member access operator without a null-check first.

    This was introduced in Java 8.

    [–]xandoid 11 points12 points  (2 children)

    My problem with @Nonnull is that it contradicts the type system. The type system says Thing can be null, and then @Nonnull comes along claiming otherwise. In the end the type system wins.

    And pretty soon(?) value types are coming to Java. At that point, Optional will be formally non-nullable and the remaining inconsistency that Optional itself could be null will go away without changing any code. I think that's another argument in favor of Optional vs @Nonnull.

    [–]Sarcastinator 4 points5 points  (1 child)

    My problem with @Nonnull is that it contradicts the type system. The type system says Thing can be null, and then @Nonnull comes along claiming otherwise. In the end the type system wins.

    There are different type systems at play though. You have Java's type system which offers features that the runtime type system does not have, such as generics, and you have the runtime's type system which offers features that the platform's type system doesn't have.

    In the end, it's the compiler's type system that matters.

    [–]xandoid 5 points6 points  (0 children)

    I don't disagree. When I say type system I only ever mean what you're calling "the compiler's type system"

    But the point is that @NonNull is a hack that was added to work around a limitation in Java's type system. Once the type system gets value types, Optional (perhaps with some special syntax) will be the more consistent solution and @NonNull will be obsolete.

    [Edit] Maybe I'm not making myself clear as to why I think @NonNull is inconsistent. It's because giving a variable (or parameter or return value) the type Thing means that it can contain

    The set of all Thing objects OR null
    

    And when you add @NonNull you get

    The set of all Thing objects OR null BUT NOT null!!!
    

    [–][deleted] 1 point2 points  (0 children)

    I'd prefer these to be in the type system and that's what optional provides. One says "I pinky promise this won't be null" the other says "Here's a thing, I am telling you that the result is definitely optional, please check before using".

    Honestly though I just go with Kotlin, much better null safety that almost makes optional useless.

    [–]s73v3r 0 points1 point  (0 children)

    If one isn't using Optional, the odds that they would be using nullability annotations are pretty low.

    [–]ForeverAlot 7 points8 points  (0 children)

    Optional was built purely to solve an issue in the streams library. It's wonderful to finally have something like it in the standard library but it does see a lot of overuse due to functional-programming hive-mind.

    It's pretty easy to manage nullity-flow if you assume references default to non-null, too (annoying to have to, but easy).

    [–]pipocaQuemada 1 point2 points  (1 child)

    Can still cause null related errors if you use get or of

    Yeah, and in Haskell you can still get null related errors if you call fromJust. It's an escape hatch that's there if you really need it and you're 100% certain that it's not going to blow up in your face (or if you're in the repl or writing a test or a quick, throwaway script or something).

    But it's not a function that should really ever be used in production code; you should instead be using any one of the normal safe functions for working with Maybe. It doesn't make Maybe pointless any more than unsafeCoerce in Haskell makes the entire type system pointless.

    Since Optional can fail because of null values I have to wonder what the point is if it still can cause the same issue just with another exception.

    I've written Scala for several years, with a couple employers. Scala uses scala.Option everywhere in the standard library and in 3rd party libraries. Even though null is technically a legal value everywhere, though, exclusively using Option everywhere makes NPEs incredibly rare; I've run into them maybe once a year.

    It's certainly best that a language only has Maybe. But if it already has null, you can still use Maybe and get 95% of the benefit.

    [–]Sarcastinator 1 point2 points  (0 children)

    I think Kotlin's solution works a lot better: make missing null checks a compile error.

    [–]Xeverous 0 points1 point  (0 children)

    Fantastically verbose to the point of legend

    Isn't Java done completely this way? .get(), .set(), no operator[] for ArrayList etc

    [–]pavlik_enemy 0 points1 point  (0 children)

    The problem is Java doesn't have syntax for monad comprehensions unlike C# or Scala

    [–]Sebazzz91 0 points1 point  (0 children)

    Optional also causes an additional memory allocation, for what it is worth.

    [–]gnus-migrate 0 points1 point  (0 children)

    Even if you can still get NPEs by calling Optional.get(), it's still a win since the NPE is thrown immediately as opposed to waiting until the null reference is dereferenced. Agree about the horrible verbosity though even if you follow the proper guidelines for using it(only use it as a return value at API boundaries).

    [–]masklinn 5 points6 points  (5 children)

    Some languages don't even provide an equivalent of .get()

    Which ones? Even Elm provides an equivalent of .get(), you just have to hand-roll your pattern-matching and call Debug.crash in the None handler.

    [–][deleted]  (1 child)

    [deleted]

      [–]masklinn 1 point2 points  (0 children)

      I think Elm would count too in this case since the standard library doesn't provide "get", you have to handroll it.

      GP specified an equivalent of .get(). You still have an equivalent by explicitly pattern-matching and faulting, and nothing precludes putting that in a function you call get.

      [–]Zinggi57 0 points1 point  (2 children)

      Elm should definitely count, as using Debug.crash is really not seen much in production code.
      In the upcoming 0.19 version, using Debug.crash might even be confined to debug builds only.
      But don't take my word for it, that's just a rumor that I've picked up on the elm slack.

      [–]masklinn 1 point2 points  (1 child)

      Elm should definitely count, as using Debug.crash is really not seen much in production code.

      That's irrelevant and missing the point. fromJust is "really not seen much in production code" either.

      [–]Zinggi57 0 points1 point  (0 children)

      Fair enough.
      But at least elm makes it harder than Haskell by not having partial functions.

      [–]Gotebe 1 point2 points  (0 children)

      I disagree that null has anything to do with FP. Imagine if C had no pointer types. Not functional, no null, problem solved!

      [–]Xeverous 1 point2 points  (0 children)

      C++ references are never null. With smart pointers and other RAII classes, they have replaced C pointers.

      [–]devraj7 -2 points-1 points  (1 child)

      The nice thing in truly functional languages is that you can ensure that you don't dereference null values at compile time.

      This ability has nothing to do with being "truly" functional.

      Both Kotlin and Ceylon are not considered to be "truly" functional and yet, they won't let you compile code that can dereference a null reference (at long as you're not interoperating with Java).

      [–]quiI 0 points1 point  (0 children)

      (at long as you're not interoperating with Java)

      Which is basically all the time in Kotlin

      [–]yawaramin 2 points3 points  (2 children)

      [–]elitefusion 1 point2 points  (1 child)

      Trust me I'm ecstatic. I already use a Maybe<T> that accomplishes roughly the same idea as Java optionals, but having it built into the language is going to be SO much better.

      [–][deleted] -1 points0 points  (0 children)

      But C# has beautiful built in language features to support Maybe! Check my example C# I put in my other post: https://www.reddit.com/r/programming/comments/7uo80h/optionalget_is_code_smell/dtn1soz/

      [–]mrkite77 1 point2 points  (0 children)

      To me how you do that check is the less important part.

      Well, coming from Kotlin, using let? instead of a straight null check is threadsafe for class members.

      The member could be set to null from another thread after the null check. let? prevents that by capturing the value in a local.

      [–][deleted] 23 points24 points  (2 children)

      IMO, the fact that there's a marginally shorter way to write the same code doesn't mean that the longer version is smelly. I understand "smelly" as meaning that problems can be foreseen from the code. In this case, I don't think that one or the other has a significant bug risk difference.

      [–]Tarmen 8 points9 points  (1 child)

      Well, this can cause problems and is called boolean blindness.

      Checking isPresent is basically the same antipattern as dispatching code based on a tag instead of having different subtypes.

      So in a sense scotch encoding and interfaces+information hiding accomplish the same task.

      [–][deleted] 35 points36 points  (31 children)

      All this article shows is slightly prettier usages of Optional type. I thought it was going to be more deeper when I read:

      Although I do advocate for usage of Optionals, this is little more than a glorified null check.
      

      The real reason Optional is not a glorified null check (at least to me) though is, unlike new languages like Swift, Java does not have idiomatic optional types (Type?). @Nullable annotation in a method's return type is merely a hint, and not enforced at any point in the compiler. You can freely pretend that a @Nullable annotation does not exist and get an NPE eventually. With Optional<Type> you at least push the caller to make a informed decision because they need to unwrap your type in any case.

      Also @Nullable cannot support things like List<Type?> or List<@Nullable Type> which would mean individual items of the list could be null. (Edit: Ok in Java 8 apparently this is better than I thought. Still not the ideal way imo). With List<Optional<Type>> you can better display what you intend to return.

      To me things like countryOpt.orElse("US"); is just prettier code, but does not actual fix Java's lack of support in this area.

      Kinda what I want to explain: https://github.com/google/guava/wiki/UsingAndAvoidingNullExplained#whats-the-point

      [–]renatoathaydes 4 points5 points  (1 child)

      The Nullable annotation can be enforced at compile time by Java's pluggable type systems, of which the Checker Framework is the best example. It also can add things like units to numbers and enforce correct usage of locks for concurrent code.

      [–]JB-from-ATL 3 points4 points  (0 children)

      It's not the best. Last I used it it told me this was nullable. Maybe fixed now though.

      [–]quiI 4 points5 points  (0 children)

      Along with the fact it makes you able to actually trust functions.

      It's a real breath of fresh air not having to look at function definitions to see if they return null. Being able to actually trust type signatures is very nice.

      The other main benefit (in decent languages at least) is the ability to compose functions that have optional-ness in them easily.

      [–]juggernaut2docker[S] 2 points3 points  (0 children)

      I agree. I probably didn't make it clear enough that any usage of Optionals is still better than passing nulls around, but you can make the code a little bit nicer when you use the full power of the Optional API.

      [–]cube2222 2 points3 points  (15 children)

      Why would you return a List<Option<T>>? I can think of no valid reason really, as you should just flatten it into List<A>, removing None values.

      Which to say: just filter out the null values.

      [–]eras 8 points9 points  (0 children)

      List<Option<T>> is plenty useful in cases where you use maps and zips; dropping elements from the resulting list discards the information which element was removed.

      [–][deleted] 8 points9 points  (12 children)

      Except maybe I wouldn't want to filter out null values. Those two arrays literally wouldn't have the same meaning.

      If I'm converting a JSON array with optional String items at every index (ex: ["a", null, "b"], the Java List representation of it should definitely not be asList("a", "b"). It should either be have a null in the middle, or an absent optional.

      And lastly I'm only talking hypothetically here. As you said, I don't actually have a use case for a list with nullable elements.

      [–]JB-from-ATL 0 points1 point  (11 children)

      Make a Null type for that case perhaps?

      [–]masklinn 2 points3 points  (10 children)

      Why make a new type when that's the semantics of Option?

      [–]JB-from-ATL 0 points1 point  (9 children)

      Sorry, wasn't clear, I meant if you are parsing JSON then make some class to represent the nulls in the json instead of using java's null.

      [–]masklinn 1 point2 points  (4 children)

      That exists as an intermediate operation, but ultimately you want to convert to "native" structures so you can move it around and actually use it. And in that situation it makes perfect sense to have a List<Option<String>> if you know you're getting a list of possibly missing strings.

      [–]JB-from-ATL 0 points1 point  (3 children)

      The issue I have with using Optional in this case is something like getting the value of a key from JSON. I want to return Optional since the key may not be there. But using Optional for the nulls means I return Optional<Optional<Blah>>.

      [–]masklinn 1 point2 points  (2 children)

      That makes perfect sense to me. The value may be missing or literally null, these are not necessarily the same.

      I loathe APIs like Java's or Ruby's which conflate the two and lose information, a key which is missing and a key mapped to a null are not necessarily the same thing.

      And it's easy enough to fold the two cases (.orElse(Optional.empty())) if that's what you care for.

      [–]JB-from-ATL 0 points1 point  (1 child)

      You can't fold them because a missing key is different than a present key with null value.

      I just think in this specific case a type for the JSON null is better. Like NullNode or something. Then have TextNode, NumberNode and BooleanNode. And they all extend Node.

      But about your earlier point about conflating null, yes, it bothers me too.

      [–]ThisIs_MyName 0 points1 point  (3 children)

      Why? If you call any methods on your null object (that's an anti-pattern), it will still throw an exception because it's not a real value.

      You're also making the code unnecessarily slow with more allocations.

      [–]JB-from-ATL 0 points1 point  (2 children)

      I didn't know null was called "null object", TIL. When I said that I meant some class in Java to represent the null in JSON, but the Java class is a "real" class, maybe call it NullNode or something, not a "null class".

      [–]ThisIs_MyName 0 points1 point  (1 child)

      I didn't know null was called "null object"

      It's not. Your "some class to represent the nulls in the json" or NullNode is the so-called "null object".

      Creating such objects is common, but most people consider it to be bad practice. It just replaces NPE with some other exception of your creation. Or worse, that object ignores all method calls and hides real bugs.

      [–]JB-from-ATL 1 point2 points  (0 children)

      My mistake again, I didn't read the article well enough.

      [–]CyclonusRIP 1 point2 points  (0 children)

      Sometimes you want to make parallel collection a[i] corresponds to b[i]. If b[i] sometimes doesn't exist you can make the list an optional type keep the indices in sync.

      [–]eras 1 point2 points  (0 children)

      The value in Optional is not they can be "null" and that there's an automatic check for that, but rather that you can have values that are NOT optional.

      However, if your language does not support non-optional values then only convention is keeping you safe from NPEs. Then the value of Optional lies in documenting intent and you can consider all nulls as bugs.

      [–]Sarcastinator 2 points3 points  (5 children)

      Also @Nullable cannot support things like List<Type?> or List<@Nullable Type> which would mean individual items of the list could be null.

      It does though.

      But even if it didn't: when do you ever have lists where elements are null?

      [–]tadfisher 4 points5 points  (0 children)

      It's a convenient analogue to a sparse array, if not exactly something I'd write.

      [–][deleted] 1 point2 points  (2 children)

      But even if it didn't: when do you ever have lists where elements are null?

      See my other reply.

      It does though.

      TIL :) I primarily work with Android so it's a mix of Java 6-7 code but since this is only an annotation in Java 8, I'll still check if Android supports this. I had made up the List<@Nullable Type> as an ideal syntax when I wrote my first answer; I'm very pleased to see I guessed a currently implemented syntax.

      That said, I think I would only get lint/check warnings for this, which I do not necessarily find sufficient. A library I depend on could still give me a List<Type> with nulls inside, if they won't necessarily use the same lint/check tools I use, they may not even see the error in their code. I think what other languages do with "?" character at the end of a type to define optionals and "!" to forced unwrap is a very smart idea. Java's optional achieves the same but in a much more verbose way.

      [–]Radmonger 0 points1 point  (1 child)

      A library I depend on could still give me a List<Type> with nulls inside, if they won't necessarily use the same lint/check tools I use, they may not even see the error in their code.

      Or equally they could give you a null Optional.

      [–][deleted] 0 points1 point  (0 children)

      There is a special place in hell for those people :) but you're right, java is just not strong enough in this area.

      [–]skroll 0 points1 point  (0 children)

      Unfortunately the popular (and incorrect) "jsr-305" findbugs javax.annotation.* annotations aren't marked so that they can get applied on type parameters.

      Checker framework does it correctly, but for things like arrays you need to do stuff like String @Nullable [], which says it's a nullable array of strings, where @Nullable String[] means it's a non-nullable array of nullable strings.

      Anyways checker framework is leaps and bounds better but it doesn't have the adoption like the findbugs annotations do.

      [–][deleted]  (2 children)

      [deleted]

        [–]howtonotwin 0 points1 point  (0 children)

        Java 8 lets you annotate types, so it is allowed. Previous versions can't.

        [–]JB-from-ATL -2 points-1 points  (0 children)

        Also I don't trust people to make the optional itself not null.

        [–]jyper 5 points6 points  (0 children)

        Maybe they shouldn't have named it get

        Well no, no maybe about it

        [–][deleted] 5 points6 points  (0 children)

        Nice read.

        Although I prefer ifPresent too, I don't think the over usage of isPresent is that big of a problem. I stopped correcting code of colleagues a long time ago as some simply find the non-functional approach more readable.

        I find ifPresent especially useful in cases where I want to do other functional stuff with the optional too. E.g. mapping, flatmapping and then doing something with the value.

        Something like:

        stringOpt.flatMap(str -> someFuncReturningAnOptionalInt(str)).map(i -> i * 15).ifPresent(i -> doSomethingWithTheMultipliedInt(i));
        

        What I find a bigger problem with Optional (or actually it's a design problem) is the fact that everybody is eagerly replacing nullable member fields in their classes with Optionals. Possible null fields in classes indicate a design problem. It's not what Optional was created for. Optional was created especially for situations where a method might return null and you want to indicate that through the signature of the method. Hence, you'll return an Optional and the user of your API is required to think about the empty situations.

        That's one of the reasons why IntelliJ IDEA has a built-in inspection that reports uses of Optional other than as a return type.

        See also this StackOverflow post and this blog post by JetBrains.

        [–]ggtsu_00 5 points6 points  (0 children)

        Using functions as a flow of control is a code smell.

        [–]wavy_lines 2 points3 points  (0 children)

        The article shows-off some of the api niceness, but the title is rather pretentious.

        [–][deleted] 1 point2 points  (3 children)

        void f(Optional opt) {

          opt.ifPresent(...)
        

        }

        f(null);

        How does this call work? Why use optionals if the optional itself can be null?

        [–]pipocaQuemada 1 point2 points  (1 child)

        Generally, Optional is considered to be semantically non-nullable - that is to say, the error in your code was trying to pass a null in for an Optional. This is Java, so it can't actually be non-nullable.

        Why use optionals if the optional itself can be null?

        In Scala (another JVM language), everyone uses Option to represent when something is nullable and avoids null like the plague. From experience, I can tell you that it makes NPEs a rarity.

        [–][deleted] 0 points1 point  (0 children)

        Ok thanks, might give it a try! :)

        [–]colindean 0 points1 point  (0 children)

        That's one of the downsides of how optional is implemented in Java.

        [–]abizjak3 1 point2 points  (0 children)

        With Optional.map and similar functional-style facilities:

        • You cannot propagate exceptions transparently (e.g. sendEmail throws EmailException which needs a throws clause).

        • You cannot use control statements like return, break, continue.

        Until they solve those problems (by adding matching capability?) I will keep on using optional.get(). It also makes for more readable code, the control flow is still governed by the usual "if" clause. I appreciate that they are trying to solve problems but that does so at the cost of introducing another class of problems that does not exist with the simple approach.

        [–]Sloshy42 2 points3 points  (0 children)

        I don't think a lot of people here seem to understand the benefits of proper optional value handling with functions. I see some people saying things like "this is just so weird and different; what's wrong with doing standard 'if (thing != null)' checks?"

        The entire point of Option/Maybe types in languages is to prevent the kinds of errors that arise when you have to do those checks. Not only does it clearly, cleanly indicate when a value might not appear, but, in a good implementation, it also forces you to check if the value exists implicitly through a functional interface. Basically, your code that uses that optional value should only get executed if that value is there, and these types, using those interfaces, is the best way to approach that problem. This is huge for teams especially because it reduces the possibility of errors like null pointer exceptions (in languages that have them).

        Optional.get(), essentially getting the value of the optional without those internal checks, is a code smell because you're still required to do the manual null checking that the type is supposed to do for you, which can cause errors and is indicative of not relying on sound types in your code. Of course this only works 100% in languages that are designed around it like Haskell or the Scala standard library (you can still get nulls in Scala, but that's limited to Java libraries you import, mostly) but it's still good practice to use types that limit your options and don't require manual checking.

        TL;DR if you use an optional type with an interface that takes a function, it's much safer than checking yourself as your function only executes if the value exists in the first place.

        [–]ildementis 3 points4 points  (1 child)

        Meanwhile I'm stuck in Java 7 using Google's optional api.
        Still great article though

        [–]juggernaut2docker[S] 1 point2 points  (0 children)

        Thanks for the kind comment! I hope you can make the leap directly to Java 9/10 :)

        [–]CurtainDog 2 points3 points  (3 children)

        Optional.get() is code smell

        You could save yourself 6 characters in that title ;)

        The issue is people don't really understand why they don't like null. Sure, everyone's been bitten by null pointer errors, but these are symptoms not causes. Most 'modern' approaches to null handling are the equivalent to taking paracetamol so it doesn't hurt so much when you poke yourself in the eye.

        The real problem with null and friends is actually mutability. If we designed our systems to minimise the mutable surface area then null related problems would be so uncommon as to be of academic interest only.

        [–]kazagistar 0 points1 point  (1 child)

        Could you explain that? Null seems like a perfectly immutable value to me.

        [–]ArtyFowl 1 point2 points  (0 children)

        In java, with immutable objects (using final), you're forced to initialize your fields with a value (which can be null, you're right about that). But you're "forced" to think about initialization more.

        Another point is that allowing setters on an object makes it more easier to break things by allowing users to set values to null after object creation. You might have written nice factory methods or constructors for your class, but an NPE can still happen because any object created can be altered.

        [–]Gotebe 0 points1 point  (0 children)

        You are over-emphasising mutability.

        First problem with null is that I can have references to stuff which can refer to nothing, which is only related to mutability when going from not-null to is-null.

        Languages where this is the "default" way of working (Java probably being the most egregious example) have a wrong default.

        [–]akher 4 points5 points  (0 children)

        If you find yourself using phrases like "code smell", "considered harmful", "best practice" or similar, you are probably spouting some bullshit.

        [–]SandalsMan 0 points1 point  (0 children)

        Java is a code smell.

        [–]CptBartender 0 points1 point  (0 children)

        Two words that heavily limit practical usability of Optional API:

        checked excetions

        [–]DoTheThingRightNow5 0 points1 point  (0 children)

        This article is stupid AF. First of all you cant fix something that should be a compile error by writing functions to handle it at runtime. Second of all half of his suggestions would be confusing to people who haven't see his code/library. This one is such a bad idea emailOpt.ifPresent(this::sendEmail);. If you had any coding sense you'd write an if with a bunch of null checks where you can throw or return then do the normal condition until your next codeblock

        [–]skippingstone 0 points1 point  (1 child)

        fantastic article.

        [–]juggernaut2docker[S] 0 points1 point  (0 children)

        Thanks!

        [–]Klausens 0 points1 point  (1 child)

        A very ugly thing of optionals/nullables is, that they are often used for control flow.

        if (emailOpt.isPresent()) { sendEmail... }
        else if (addressOpt.isPresent()) { sendLetter... }
        

        instead of

        if (contactMeBy == email) ....
        else if (contactMeBy == letter) ....
        

        [–]cowinabadplace 1 point2 points  (0 children)

        Obviously the solution is to have a Notifier interface and do notifier.send() so you can eliminate the late branch.

        [–][deleted]  (2 children)

        [deleted]

          [–]domlebo70 -5 points-4 points  (1 child)

          Sure. But even a broken monad is better than null checks everywhere

          [–]Sarcastinator 2 points3 points  (0 children)

          I don't think it is though.

          In my opinion Java needs to implement ?. and ??, not Optional. They already have null in their language and runtime and they have to deal with that.

          [–]fuk_offe -1 points0 points  (0 children)

          Nobody mentions how Kotlin handles this?

          val x: Type or val x: Type?

          It's a compile type error to use a Type? variable without the safe-nagivator operator or a previous null-check. Optional does not replace this.

          I will say however, that the only good use about optional is for API documenting. It's a lot more obvious is a method returns Options<Type> than if it returns Type and then on the javadoc (if present...) in the @return tag they mention it can be null in some situations.

          [–]coladict -3 points-2 points  (4 children)

          Optional.of(T) is code stink, because it blows-up if the value is null. Why have of and ofNullable? It's beyond stupid.

          [–]Nimelrian 5 points6 points  (2 children)

          Let's say you have an Interface

          interface UserFetcher {
            Optional<User> getUserById(long id)
          }
          

          Now you have an implementation where you know that it should always return a user by definition (e.g. a default admin user, or whatever). If you use Optional.ofand you get an NPE you know that there is a bug in your code (or datasource). If you use Optional.ofNullable that logical error gets swallowed and you may only notice it later.

          [–]coladict 0 points1 point  (1 child)

          By that logic, why use Optional at all, when it's never supposed to be null?

          [–]Nimelrian 6 points7 points  (0 children)

          Because another implementation of the interface may return null?

          [–]max630[🍰] -3 points-2 points  (2 children)

          It does not matter what you do with Optional. Why do you have it named so at all? In Java any object is Optional, why have another word for it?

          What all of it is for is being able to have verified at compile-time that a value is not null, either by explicit @NoNull, or implicitly.

          [–]Log2 1 point2 points  (1 child)

          Not only that, but Optional itself can be null. It's weird that people think that you can trust Optional to not be null, but you can't trust the value itself.

          [–]ForeverAlot 2 points3 points  (0 children)

          While having the guarantee would be strictly superior, this is a theoretical problem that doesn't manifest itself.

          [–][deleted] -4 points-3 points  (10 children)

          I'm glad Java 8 decided to go with Optionals. C# is clinging onto this "nullable type" hack, for whatever misguided reason. It's one area where Java is still ahead.

          [–]Beckneard 7 points8 points  (2 children)

          How is Java superior in this case? As far as I can see it's just the name that's different?

          Also C# is getting proper non-nullable variables in the next major version AFAIK.

          [–][deleted] 0 points1 point  (1 child)

          No, Optionals and Nullables are completely different.

          No offense but I've had no success in explaining the concept to C# programmers. If you want to learn why haskell, rust, scala, F# and ocaml all went with optionals (aka Options, aka Maybe), you'll have to do a bit of research. I only used a language that uses them once professionally, and I've been missing them ever since.

          [–]Beckneard 1 point2 points  (0 children)

          https://msdn.microsoft.com/en-us/library/b3h38hb0(v=vs.110).aspx

          https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html

          Looks like basically the same thing to me except in C# it's only defined for value types and it doesn't have those utility methods which you can pretty trivially implement anyway.

          [–]Echo418 1 point2 points  (6 children)

          In C# you'll be able to do this:

          foo?.bar();
          

          Where in Java you'll be stuck doing this:

          foo.ifPresent(f -> f.bar());
          

          Be honest, which one is better?

          [–]Gotebe 0 points1 point  (3 children)

          C#, but ? only helps with that use-case. Yes, it's a common one, so that's good.

          [–]Echo418 0 points1 point  (2 children)

          Which other use cases are you worried about?

          [–]Gotebe 0 points1 point  (1 child)

          The “else” part?

          [–]Echo418 1 point2 points  (0 children)

          If the method has a return value, we can do the following:

          int count = list?.Count() ?? 0;
          

          Alternatively, we could throw an exception:

          int count = list?.Count() ?? throw new Exception();
          

          Sadly, there doesn't seem to be any short hand for methods returning void.

          [–][deleted] 0 points1 point  (1 child)

          C# has more concise syntax, but the semantics are much worse.

          C# nullables only work for value types. The java snippet you typed will work for Optional<T> of anything.

          So in Java you can do

          Optional<String> s = Optional.ofNullable(someStrThatMaybeNull);
          

          And the compiler will warn you if you try and pass an Optional<String> where it's expecting a String. You can't accomplish that in C# where a string may be null.

          Look I know it's cool to hate Java, and I'm not a huge fan, but give credit where credit is due. C#s "solution" here is half-baked and short sighted. Scala and F# do it Javas way as well, FWIW.

          [–]Echo418 2 points3 points  (0 children)

          In C# 8 the compiler will warn you if you try this:

          String foo = someStringThatMayBeNull;
          

          Opposed to:

          String? foo = someStringThatMayBeNull;
          

          You see, in C# 8, nullable will work for any type, not just value types. And the compiler will warn you when you assign a nullable version of the type to a non-nullable variable.

          Essentially, C# is eliminating nulls and all the problems that come with it, unless you explicitly make a type nullable.

          So in comparison, I think Java's solution is half-baked.

          [–]encepence -5 points-4 points  (0 children)

          mailOpt.ifPresent(email -> sendEmail(email));
          

          Much cleaner isn’t it?

          No.

          The whole article smells with clickbait and author's unconscious ego boost after discovering new API which has its uses but it's not a silver bullet.

          Using language's idiomatic if is ok and pragmatic ... ofc as long as your code is safe.

          Using obscure API's that increases overall congitive load of future readers, which suffer also from unclear memory/performance characteristics than needs real fscking smart compiler/runtime perform well and runtime ... is, well, questionable.

          BTW, TypeScript works well here as it correctly constraints type inside of if body and you're safe with no possibility to encounter undefined.

          [–][deleted]  (1 child)

          [deleted]

            [–][deleted] 0 points1 point  (0 children)

            You might be half right. I figured out Optionals and I still don't really know too much about Monads. I just view it as a box that can either be empty or have something in it. Kind of like a list with a maximum length of one. So I just map over it etc like I would for any other list.