3 ms·
That is a useful way to think about it for sure, I’m mostly using it as an illustration of what is probably a philosophical difference between myself and the Ru
by voidhorse 4y ago
That is a useful way to think about it for sure, I’m mostly using it as an illustration of what is probably a philosophical difference between myself and the Rust maintainers; in other words, I don’t see why we need if let when we already have match with _ wildcards. It’s the sort of syntactic shortcut that gives authors of code relatively little benefit (save a few keystrokes) and readers of code yet one more syntactic variation to contend with.
I guess another way of putting it is that I think Rust has a lot of sugar that’s confusing.
Kotlin is an example of a language that has a lot of similar syntactic shortcuts and functional underpinnings that implements them in a more readable and consistent fashion imo.
- burntsushi 4y agoI could live without 'if let'. I'm not a huge fan of it either, although I do use it. Its most compelling benefit to me is not that it saves a few keystrokes, but that it avoids an extra indentation level. Compare (taking from a real example[1]): if let Some(quits) = args.value_of_lossy("quit") { for ch in quits.chars() { if !ch.is_ascii() { anyhow::bail!("quit bytes must be ASCII"); } // FIXME(MSRV): use the 'TryFrom<char> for u8' impl once we are // at Rust 1.59+. c = c.quit(u8::try_from(u32::from(ch)).unwrap(), true); } } with: match args.value_of_lossy("quit") { None => {} Some(quits) => { for ch in quits.chars() { if !ch.is_ascii() { anyhow::bail!("quit bytes must be ASCII"); } // FIXME(MSRV): use the 'TryFrom<char> for u8' impl once we are // at Rust 1.59+. c = c.quit(u8::try_from(u32::from(ch)).unwrap(), true); } } } The 'for' loop is indented one extra level in the latter case. With that said, I do also use 'if let' because it saves some keystrokes. Taking from another real example[2], compare: if let Some(name) = get_name(group_index) { write!(buf, "/{}", name).unwrap(); } with match get_name(group_index) { None => {} Some(name) => { write!(buf, "/{}", name).unwrap(); } } (I could use '_ => {}' instead of 'None' to save a few more.) I do find the 'if let' variant to be a bit easier to read. It's optimizing for a particular and somewhat common case, so it does of course overlap with 'match'. But I don't find this particular overlap to be too bad. It's usually pretty clear when to use one vs the other. But like I said, I could live without 'if let'. It is not a major quality of life enhancement to me. Neither will its impending extensions. i.e., 'if let pattern = foo && some_booolean_condition {'. [1]: https://github.com/BurntSushi/regex-automata/blob/fbae90682305b1c1562c5fc2fa6337cfb1d161a5/regex-cli/src/config.rs#L1533-L1542 https://github.com/BurntSushi/regex-automata/blob/fbae906823... [2]: https://github.com/BurntSushi/regex-automata/blob/fbae90682305b1c1562c5fc2fa6337cfb1d161a5/regex-cli/src/cmd/captures.rs#L307-L309 https://github.com/BurntSushi/regex-automata/blob/fbae906823...
- saurik 4y agoI don't code in Rust--and thereby might be expected to not know all of these patterns and want to have to learn fewer bits--and yet I agree with you. I feel like removing this "if let" variant would be similar to saying we don't need if statements as they are equivalent to a loop that ends in break. I actually even will say the if let is much easier to read as with the match I have to check why it is a match and verify it has the None case--similar to checking if a loop is really going to loop or if it always ends in break--whereas I can skip all that work if I see the "if".