4 ms·
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
by Subsentient 6y ago
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.
- conradludgate 6y agoYou can do something like that ``` let x = Some(1); let x = match x { Some(x) => x, None => return, }; assert_eq!(x, 1); ```
- Zababa 6y agoHN 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 https://news.ycombinator.com/formatdoc
- seeekr 6y agoCouldn't this "inverse if let" be provided with a simple macro? Is that where you encountered bugs in the borrow checker?
- EugeneOZ 6y agoTry methods "is_err", "is_ok"; or for Option: "is_some", "is_none".
- duckerude 6y agoThat's not great if you still want to use the underlying value, because then you need to unwrap it later.
- tiddles 6y agoThe 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..
- gardaani 6y agoI 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/ https://szymonkrajewski.pl/why-should-you-return-early/ [2] https://github.com/rust-lang/rfcs/issues/2616 https://github.com/rust-lang/rfcs/issues/2616 [3] https://github.com/rust-lang/rfcs/pull/1303 https://github.com/rust-lang/rfcs/pull/1303
- danappelxx 6y agoI 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 };
- papaf 6y agoI use match as an inside out 'if let' but in this particular case I prefer to: let value = value.ok_or(MyError)?;
- exrook 6y agoI'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-features/try-blocks.html https://doc.rust-lang.org/nightly/unstable-book/language-fea... [1] https://github.com/rust-lang/rust/issues/31436 https://github.com/rust-lang/rust/issues/31436
- Arnavion 6y ago`?` 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).
- nulptr 6y agoYeah, 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)) }
- safarimonkey 6y agoI 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