News for hackers. Stuff that matters.
Re:Where Everything Went Wrong: Error Handling and Error Mes... by Subsentient on Friday February 19, 2021 @04:54AM (#26191326)
For the mostpart, Rust error handling is okay. What really rustles my jimmies, however, is the often mandatory indentation because of a lack of an inverse "if let". I prefer to bail out of a block if a condition is NOT met, rather than execute another nested block if it IS met. Rust makes that harder than it should be. It's good code hygiene in every other language, and Rust makes it painful in places. I've even been stopped from doing this by literal bugs in the borrow checker.
Re:Where Everything Went Wrong: Error Handling and Error Mes... by gardaani on Friday February 19, 2021 @06:03AM (#26191779)
I totally agree. I love Swift's guard let. It makes early returning [1] easy:

    guard let value = optvalue else {
        return // optvalue is none
    }
There has been several proposals [2][3] to fix it in Rust but they don't seem to go anywhere.

I'm using this in my own code now to unwrap or return (it looks stupid):

        let value = if let Some(value) = optvalue {
            value
        } else { // optvalue is none
            return;
        };

[1] https://szymonkrajewski.pl/why-should-you-return-early/

[2] https://github.com/rust-lang/rfcs/issues/2616

[3] https://github.com/rust-lang/rfcs/pull/1303

Re:Where Everything Went Wrong: Error Handling and Error Mes... by danappelxx on Friday February 19, 2021 @03:14PM (#26197508)
I missed `guard let` for a while too, but eventually stumbled upon this pattern which is almost as good:

    let value = match value {
        None => return,
        Some(value) => value
    };
Re:Where Everything Went Wrong: Error Handling and Error Mes... by papaf on Friday February 19, 2021 @06:17PM (#26199362)
I use match as an inside out 'if let' but in this particular case I prefer to:

  let value = value.ok_or(MyError)?;
Re:Where Everything Went Wrong: Error Handling and Error Mes... by exrook on Friday February 19, 2021 @06:04AM (#26191782)
I'm confused, have you found the try operator ("?") insufficient for your use cases? I believe it does what you are describing, ex:

    fn process_file(p: Path) -> Result<String, io::Error> {
        let file = File::open(p)?; //Return err if file can't be opened
        let mut out = String::new();
        file.read_to_string(&mut out)?; // Return err if read fails
        out
    }
If you want to handle the error case within the same function `try` blocks are available in nightly[0] and will eventually come to stable[1]

[0] https://doc.rust-lang.org/nightly/unstable-book/language-fea...

[1] https://github.com/rust-lang/rust/issues/31436

Re:Where Everything Went Wrong: Error Handling and Error Mes... by Arnavion on Friday February 19, 2021 @04:09PM (#26198057)
`?` only helps if the thing you want to do on Err is return from the whole function. You can't use it for finer-grained break / continue / exit-from-current-block (until `try` blocks are stabilized).
Re:Where Everything Went Wrong: Error Handling and Error Mes... by tiddles on Friday February 19, 2021 @05:27AM (#26191519)
The most common time this comes up for me is trying to use continue/break if a value is None/Err :

  loop {
    let thing = match foo() {
      Some(bar) => bar,
      None => continue,
    }
  }
Yet I still always first try to put the continue in an unwrap_or_else first..
Re:Where Everything Went Wrong: Error Handling and Error Mes... by nulptr on Friday February 19, 2021 @10:16AM (#26194038)
Yeah, this is irritating... one workaround for this is to do:

(in the context of walking a tree...):

    fn get_depth(root_opt: &Option<Box<TreeNode>>) -> usize {
        let root = match root_opt {
            Some(root) => root,
            None => return 0;
        };

        1 + std::cmp::max(get_depth(root.borrow().left), get_depth(root.borrow().right))
    }
Re:Where Everything Went Wrong: Error Handling and Error Mes... by safarimonkey on Tuesday February 23, 2021 @05:46AM (#26235795)
I ran into this the other day, and it took me a moment to realise that I could just use `matches!`:

    // want to do this
    if not let Some("pattern") = val {
        doSomething();
    }

    // can instead do
    if !matches!(val, Some("pattern")) {
        doSomething();
    }
edit: formatting
Re:Where Everything Went Wrong: Error Handling and Error Mes... by seeekr on Friday February 19, 2021 @05:04AM (#26191383)
Couldn't this "inverse if let" be provided with a simple macro? Is that where you encountered bugs in the borrow checker?
Re:Where Everything Went Wrong: Error Handling and Error Mes... by EugeneOZ on Friday February 19, 2021 @05:05AM (#26191386)
Try methods "is_err", "is_ok"; or for Option: "is_some", "is_none".
Re:Where Everything Went Wrong: Error Handling and Error Mes... by duckerude on Friday February 19, 2021 @05:15AM (#26191434)
That's not great if you still want to use the underlying value, because then you need to unwrap it later.
Re:Where Everything Went Wrong: Error Handling and Error Mes... by conradludgate on Friday February 19, 2021 @05:28AM (#26191528)
You can do something like that

``` let x = Some(1); let x = match x { Some(x) => x, None => return, };

assert_eq!(x, 1); ```

Re:Where Everything Went Wrong: Error Handling and Error Mes... by Zababa on Friday February 19, 2021 @06:41AM (#26192065)
HN doesn't uses Markdown syntax for formatting: "Text after a blank line that is indented by two or more spaces is reproduced verbatim. (This is intended for code.)" https://news.ycombinator.com/formatdoc