This is a really simple silly thing I just realized, but I noticed I have a lot code that looks something like this:

fn foo() -> Result<(), Error> {
    // do something
}

fn bar() -> Option<()> {
    let Ok(f) = foo() else {
        return None;
    };
}

I hated that if-statement. I realized today that I could simplify to:

fn bar() -> Option<()> {
    let f = foo().ok()?;
}

And that cleaned up my code a lot. It’s a tiny thing, but when it’s okay to discard the error from the result, makes such a big difference when you have a lot of them!

  • tatterdemalion@programming.dev
    link
    fedilink
    arrow-up
    21
    ·
    1 year ago

    Do you really discard errors this often? I would say almost all of my Results get propagated to the caller via ? and handled in one place near the start of the stack.

    • kiaOP
      link
      fedilink
      English
      arrow-up
      3
      ·
      1 year ago

      A lot of the time, I have these around places where I’m reading from a file. If reading causes an error, regardless of what the error is, I just return None and a new file is created.

      • nous@programming.dev
        link
        fedilink
        English
        arrow-up
        17
        ·
        1 year ago

        That is a terrible time to throw away the error. Best to actually check for file not exists error and created the file only then. Other errors are important to see to debug why things are failing.

        It is very annoying to have a tool tell you it failed to create a file when the file exists but it just cannot read it for some reason. You can spend ages jumping down the wrong rabbit whole if you don’t realize what is happening.

        • Turun@feddit.de
          link
          fedilink
          arrow-up
          5
          ·
          1 year ago

          You’re not wrong, but there are some situations in rust that are just so full of errors. Not because the situation will regularly fail in a variety of ways, but because rust can’t prove that there never will be errors. And depending on how important the application is (vs the required boilerplate) just ignoring errors can be a reasonable choice

          File system handling has been named. Creating a tokio runtime is also just .unwrap() whenever I have seen it. Creating a python module with pyo3 contains a big chunk of m.add_function(…?)?; which may just as well be unwrap()s.

          • nous@programming.dev
            link
            fedilink
            English
            arrow-up
            6
            ·
            1 year ago

            Unwaps or panicing or returning the error to the caller are all forms of handling the error - crash the program with a message that can tell you what went wrong and where in the code it happened. These give you a path to see what went wrong

            But silently ignoring an error is rarely the right move. It stops you from seeing what the cause of the problem is and often leads to some weird non sensical failure somewhere else. Which I have seen time and time again lead to hours down a rabbit hole trying to understand why things are not working because you are missing the root cause of the problem.

            There are times when you really don’t care about a failure at all, but those times are rare and should be carefully considered first, crashing the program is generally the first thing you should do if you are unsure.

            • Turun@feddit.de
              link
              fedilink
              arrow-up
              3
              ·
              1 year ago

              Fair enough. I didn’t consider “just crash lol” as handling the error, but your distinction is a good one.

        • BB_C@programming.dev
          link
          fedilink
          arrow-up
          4
          ·
          1 year ago

          That is a terrible time to throw away the error. Best to actually check for file not exists error and…

          lol

          This is unintentionally funny considering how exists() is implemented (which is why we have try_exists() now).

        • kiaOP
          link
          fedilink
          English
          arrow-up
          2
          ·
          1 year ago

          Yeah that’s a good point. This is a special case where the file is simply caching runtime results so errors surrounding it not being read aren’t a big deal.

      • BB_C@programming.dev
        link
        fedilink
        arrow-up
        3
        ·
        1 year ago

        I don’t get it!

        If the T in Result (and presumably Option) is (), then why not just use is_ok()/is_err() from the caller side?

        Other Tips:

        • bool has then() and then_some() methods in std now.
        • You can transpose() in both directions between ResultOptionᐸTᐳᐳs and OptionResultᐸTᐳᐳs