Rust Additions for GCC 15 Bring Support for If-Let Statements
phoronix.com
phoronix.com
BTW: Here's a good reference to the differences between "if" and "if let" - https://web.mit.edu/rust-lang_v1.25/arch/amd64_ubuntu1404/sh...
When I first started learning Rust several years ago, I shared your viewpoint. With a heavy preference for C++ syntax, I thought Rust looked atrocious.
Then I learned it. I got good with it. I got comfortable with it. I switched from VS Code based IDEs to vim, then to IDEs with vim bindings (trying Zed now). Now, Rust reads like a dream -- aside from lifetime specifiers, which I think could be much smarter than they are now.
Anyway, it has superior pattern matching and code searching. snake_case is easier to navigate than camelCase or PascalCase. Keywords are short and easily recognizable. Branching logic is much, much easier to follow. Error handling is explicit and also easier to follow (and I started out really missing try-catch). Code gen with macros eliminates a lot of headaches. A 1st class package manager that is fast & can be easily inspected, that seamlessly integrates into the code...the list goes on.
The point is, it is a paradigm shift that doesn't hide much of anything away. When you consider there is no GC and you are in full control of memory, that there are strict syntax and styling rules that make the global Rust codebase universally accessible, once you switch to it you find yourself wishing everything was written in Rust. That is why people using it want to rewrite everything, even well established packages. A Rust-only codebase is buttery smooth.
Usually people will try to make it the first letter of something meaningful, but it is still much harder to parse.
My own preference is to use more descriptive names except in trivial cases. Having the lifetime mirror a struct member name or a parameter name is really helpful for understanding them, in my opinion.
I have a backlog item to find Rust docs which use a concise lifetime name but could value a better one, however there aren't actually that many cases other than the scoped threads which do indeed name the scopes 'scope and 'env showing that we can give these meaningful names.
First example with `match` seems to me already more readable than `switch` statement with breaks.
>match option
>if option.is_some()
>Neither of these options is particularly appealing.
There’s the answer. The new syntax is just particularly appealing.
Does “if let some of x be assigned an option:” make better sense and sound greater than “match option, some of x:” and “if option is some:”?
while let Some(work) = inbox.pop() { /* ... */ }
[edited: thanks HN, of course since this is code I don't need to escape the asterisks, unless I do]It's not that... well, it might be, but I use pattern matching fairly regularly in a number of languages. But Rust has hijacked the variable syntax and changed it beyond recognition: there's no matching operator being used; the same code does different things based on its surroundings:
// This causes a compilation error
let Some(work) = inbox.pop()
// But putting it 1:1 within a while statement is fine?
while let Some(work) = inbox.pop() { /* ... */ }
Whereas, with Java's pattern matching: while (inbox.poll() instanceof final Work work) { /* ... */ }
It borrows the variable declaration syntax too, which can be extracted fine without issue, but there's an operator being used to express that pattern matching is happening.Different languages have different uses, histories, and quirks, yes, and this is by no means to suggest that Java is a better language or that it doesn't have its own flaws. But Rust coopting of that syntax makes the language harder to learn and harder to comprehend at a glance, in my opinion. It seems to be like one of those situations where, once you learn it, it's fine, but that's my point.
I'll assume you know you missed a semi-colon, so we'll fix that, which still gets us a compiler error, but specifically the diagnostic says: pattern `None` not covered and it suggests:
let Some(work) = index.pop() else { todo!() };
You seemed puzzled by the fact we can use this pattern for let while, but of course when our pattern doesn't match (for None) the loop ends, that's what a while-let loop does, the if expression which may not match needs a clause for the case where it doesn't match, the suggestion is an else clause.Remember Rust is a statically typed expression language so Python type situations where maybe the pattern matched or maybe it didn't and something will happen but the language doesn't promise what, those aren't OK because we have static typing, what is the type of "Eh, I don't know, whatever" ?
Edited:: Aha, I realised you wrote "1:1 within a while statement" and now I think I see the problem. That's not a while statement, Rust doesn't have those - it does have while loop expressions - but this isn't one of those either, this is while let, it's different.
This isn't a while loop where the while condition happens to be a variable assignment, Rust doesn't have that. There's a reason while let has a whole separate entry in the book. This is syntax for a loop which repeatedly performs a pattern match and always exits when it fails.
But just for fun, let's make it compile!
enum Result<T> {
Some(T),
}
use Result::Some;
fn pop() -> Result<u32> {
Some(42)
}
fn main() {
// This doesn't cause a compilation error
let Some(work) = pop();
}Kind of ironic now with Cobol being added in GCC 15, joining Modula-2, D, Rust, Fortran, Ada, C, C++ collection of frontends.