fn main() {
let x = 'x';
let c = 'c';
match c {
x => println!("x: {} c: {}", x, c),
}
println!("x: {}", x)
}
In my opinion, the value of expression c in match is 'c'. And it doesn't match the value of x, then it would not perform the println!.
Surprisingly! The code can run!
So the value of 'x' should be 'c'. How can this happen???
You are actually not comparing c to x, but capturing c in a new x. It's as if you would write let x = c;, but with the difference that it will check if the value of c matches the pattern in question.
If this was an actual comparison, you would get an error where the compiler complains about a non-exhaustive match, since it wouldn't cover all the possible scenarios.
Your words are very helpful.
the process is : let x = c, then use the value of x in the subsequent println!. am I right?
But I can't really get the meaning of
it will check if the value of c matches the pattern in question
what's the pattern in this situation, could you give me more details, i am a beginner.
many thanks!
The pattern is, in this case, "any value x", or in Rust: x. It may be easier to demonstrate with a more complex value:
let maybe_c = Some('c');
match maybe_c {
Some('a') => println!("found the 'a'"),
Some(x) => println!("it was an '{}'", x),
None => println!("found nothing"),
}
The patterns are whatever is on the left side of the => and a branch will be chosen depending on which one matches the actual value.
FYI, the left hand side of let x = c is also a pattern, but it must always match. This lets you destructure values:
struct Foo {
a: u8,
b: u8,
c: u8,
}
//Create a value...
let foo = Foo {
a: 1,
b: 2,
c: 3,
};
//...and take it apart
let Foo { a, b, c } = foo;
println!("a = {}, b = {}, c = {}", a, b, c);
Shadowing is only a problem, in my experience, when using short/one letter names. Descriptive variable names lowers the risks immensely.
Edit: Actually, what I think helps is to think in a data-flow way, instead of just "let me put this somewhere". Names can be recycled if it's the same data, but not otherwise.
This prints "it was an 'c'", but to me, it could have just as well printed "found the 'a'" because maybe_c is neither an x nor an 'a'. Why did the compiler prefer the Some(x) to the Some('a')? Neither has a variable binding such as "let x ...".
In the original code, "let x = 'x';", the x is not mutable. Yet the value of x is allowed to change to a c in the match statement. Can you speak to that? Later, with your "Some" statements, it looks like you are saying that any letter or group of letters can be substituted instead of x because Some(x) is defining the variable x. For example,
Some(abcde) => println!("it was an '{}'", abcde),
Going back to the original code with "x => println ...." being the only statement within the match clause, it looks like any valid variable name on the left of the => symbol will be taken as "I am a new variable, or I am redefining the named variable, and I am a catchall that will match anything". Is this understanding correct?
You got it more or less correct. The original is confusing because the name x is reused in a new variable. The match statement defines a new x that shadows the old one within that particular arm. The old x is still there, but it's temporarily unaccessible.