3 ms·
I know GAT is a "bigger feature" for the language but personally I'm most excited about `let else`. It is very common to write code such as: let foo = match
by kevincox 4y ago
I know GAT is a "bigger feature" for the language but personally I'm most excited about `let else`. It is very common to write code such as:
let foo = match do_something() {
Ok(f) => f,
Err(e) => {
// Do some error handling, maybe log a warning, maybe skip this item and continue...
}
};
This small change makes that so much more clear, removes the silly first row and removes a level of indentation.
let Ok(foo) = do_something() else {
// Do some error handling, maybe log a warning, maybe skip this item and continue...
};
- echelon 4y agoSo much of my code is this. I love this addition too. I'm very impressed with how much good stuff is in this release. The Rust team is killing it.
- adamch 4y agoExcept the let-else version has one big disadvantage. The 'match' version has bound the error to `e`, so you can log that error or inspect it. The 'let-else' version can't read the error, so its log message can't be as useful. You can't check if it's a specific error, or include the error in logged messages. It's still convenient, but in really limited circumstances, AFAICT. This week I'll be going through the various Rust projects I maintain at work, seeing if there's useful places for let-else.
- vasilakisfil 4y agoyou are right, not so useful for Result type, but still, it comes handy for Option types (since None doesn't hold anything).
- etra0 4y agoAgree, I don't know if it's that useful for `Result<T>`, but for `Option<T>`, there has been a couple of times I've written if foo.is_none() { return; } let foo = foo.unwrap() Now I can do simply let Some(foo_unwrapped) = foo else { return; } which is prettier than the `if let (...)` to just unwrap it IMO.
- mintplant 4y agoWithout let-else, you could write that as: let foo_unwrapped = match foo { Some(foo_unwrapped) => foo_unwrapped, None => return, }; Not as pretty, but you don't have to unwrap.
- bonzini 4y agoFor Result it's probably more common to use ?, alternatively you could use let x_result = something; let Ok(x) = x_result else { ... } But I expect that it will be used mostly with Option, as in "else continue" or "else break".
- cercatrova 4y agoCouldn't you match on Err? That's how I do it with `if-let` anyway if let Error(e) = my_func() { //... Do something with e }
- kibwen 4y agoYes, though that doesn't put the value of the `Ok` variant into any scope. At the end of the day, if you need maximum flexibility for whatever you're doing then you still need to reach for `match`, even if it's a bit more verbose.
- dllthomas 4y agoI mean, in all cases `if let` is for when there's nothing in other constructors that you want to talk about. That'll be every time you match on `Option<T>`, `Result<T, ()>`, or `Result<(), T>`, all of which come up at least occasionally, and will occasionally be other cases. Edited to add: I don't mean to imply that you should always use `if let` for those cases - that may be but I reserve judgement on it.
- jamincan 4y agoI think in any instance where you need to unpack every variant, `match` will almost always be the least verbose option.
- adamch 4y agoUpdate: I did go through every `match` statement in my 16k-line Rust project at work, and I found a number of places where it was useful. My commit to use let-else had 10 files changed, 27 insertions(+), 48 deletions(-).
- est31 4y ago> This week I'll be going through the various Rust projects I maintain at work, seeing if there's useful places for let-else. If you want help from automation, you can wait a few days until the manual_let_else clippy lint arrives on nightly. It's going to be one of the pedantic lints, and recognizes some obvious places where let else would make sense (not all but many). It should arrive in one week-ish, depending on when the next clippy update is in nightly.
- 63 4y agoHow does this differ from the if-let syntax we already have? I'm a bit of a rust novice.
- kevincox 4y agoWith if-let you still need to "pass down" the variable. It would look like: let foo = if let Ok(f) = do_something() { f } else { // Do some error handling, maybe log a warning, maybe skip this item and continue... }; It's similar to `let else` but you still need this extra `f` variable that isn't really adding clarity.
- deleted 4y ago[deleted]
- ragnese 4y agoIt's mostly about avoiding nesting. Honestly, I'm still pretty ambivalent about it. But, before you might do: if let Some(x) = maybe_x { // do stuff with x } else { return; } now, you'd do: let Some(x) = maybe_x else { return; } // do stuff with x If you have several instances of this kind of thing, the nesting can be pretty ugly and hard to read, so we'd sometimes do janky things to avoid the nesting, like: let x = if let Some(x) = maybe_x { x } else { return; }; or, if let (Some(x), Some(y)) = (maybe_x, maybe_y) { // do stuff with x and y with only one layer of nesting } else { return; }
- __s 4y agoIt doesn't differ by much, here's an example of let-else replacing if-let: https://github.com/serprex/NULL/commit/9ab765c5089ce1f0e32cee78b191d32044c30b25 https://github.com/serprex/NULL/commit/9ab765c5089ce1f0e32ce... In another codebase I had something like let msg = if let Ok(msg) = ... { msg } else { continue }; becoming let Ok(msg) = ... else { continue };
- dwaite 4y agoSwift has `guard else`, including `guard let else` for preconditions, where you only put the error responding code and where the compiler forces you to exit the current context (e.g. return a value, throw an error, etc). It is nice for collapsing pyramids of doom that come from normal precondition checking. You can put multiple comparisons or variable assignments into a a single guard as well, separated by commas. It does not support binding to the error in a Result though, so for these you usually still get more readable code handling these with try/catch, with the corresponding nested code block.