Trying to replace following snippet with if statement with match in rust playground , some hint would be helpful:
fn main() {
let my_number = 5;
if my_number % 2 == 1 && my_number > 0 { // % 2 means the number that remains after diving by two
println!("It's a positive odd number");
} else if my_number == 6 {
println!("It's six")
} else {
println!("It's a different number")
}
}
Note that the temporary scopes in match expressions are slightly different. This can be surprising:
use std::cell::RefCell;
fn main() {
let x = RefCell::new(0);
// this works:
if *x.borrow() < 5 {
*x.borrow_mut() += 1;
}
// this will panic:
match *x.borrow() < 5 {
true => *x.borrow_mut() += 1,
_ => (),
};
}
Compiling playground v0.0.1 (/playground)
Finished dev [unoptimized + debuginfo] target(s) in 1.62s
Running `target/debug/playground`
thread 'main' panicked at 'already borrowed: BorrowMutError', src/main.rs:11:20
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
fn main() {
let my_number = 5;
match my_number {
n if n % 2 == 1 && n > 0 => println!("It's a positive odd number"),
6 => println!("It's six"),
_ => println!("It's a different number")
}
}
In theory, every if statement can be translated into a match statement (e.g. match cond { true => true_value, false => false_value }), but... just because you can do something doesn't mean you should.
If you are just changing control flow based on a predicate (e.g. my_number % 2 == 1 && my_number > 0) then the if statement will almost always be more readable and require less code. Where match really shows off its value is more complex control flow where you want to bind to a struct field or an enum variant and do custom logic in one statement.
For example,
struct Person { name: String, age: u32 }
match db.lookup_person_by_name("Michael") {
Some(Person { age, .. } if age % 2 == 1 => println!("Michael has an odd age"),
Some(Person { .. }) => println!("Michael is in the database"),
None => println!("There is no Michael in the database"),
}
I generally agree, but note that the revised match avoids repeating my_number by binding the value to the shorter name n. This is why I think the match has some advantages in that case.
Hers some creative use of match featuring matching on tuples and matching against ranges; mostly for educational purposes, I'm not sure if I'd actually want to write it this way
fn main() {
let my_number = 5;
match (my_number, my_number % 2) {
(1.., 1) => println!("It's a positive odd number"),
(6, _) => println!("It's six"),
_ => println!("It's a different number"),
}
}
I tried this, but it doesn't work with stable Rust:
#![feature(if_let_guard)]
fn main() {
let my_number = 5;
match my_number {
n if let (1.., 1) = (n, n % 2) => println!("It's a positive odd number"),
6 => println!("It's six"),
_ => println!("It's a different number"),
}
}
Oh right, it's reversing the order but works fine:
fn main() {
let my_number = 5;
match my_number {
n if matches!((n, n % 2), (1.., 1)) => println!("It's a positive odd number"),
6 => println!("It's six"),
_ => println!("It's a different number"),
}
}
Actually I saw matches! in the error message of stable Rust, but didn't try it, as it felt like not really exploiting the language construct. But I guess matches! is a pretty basic thing, plus it's in std.