Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can you use a previously undeclared name in a match?

I'm experiencing a problem understanding this code from the second chapter of the book:

let guess: u32 = match guess.trim().parse() {
    Ok(num) => num,
    Err(_) => continue,
};

My problem is with Ok(num) => num: parse() returns a value (either Ok or Err), match compares that returned value to the first arm. If those match, the expression will execute the statement beside the first arm, right?

In Ok(num), num seems to have popped up abruptly, since there was no declaration of num in previous code. Same with the statement, => num: num was suddenly in scope. So

  1. If I'm guessing it right, match matches the returned value with Ok(), then assigns whatever number that is (inside Ok) to num. But why is num at the right suddenly usable?
  2. If I guessed right, what's the difference of Ok(num) and Ok(_)?
like image 776
Jeff White Avatar asked Jan 02 '23 03:01

Jeff White


1 Answers

If we start with where Ok and Err come from, we might get a better idea. They are a part of the Result enum defined like:

enum Result<T, E> {
   Ok(T),
   Err(E),
}

T and E are generic types. match itself is like C's switch statement but more flexible.

The general form of match itself is:

match value {
    pattern => expr,
    ...
}

If those match, the expression will execute the statement beside the first arm, right?

Yes

But why is num at the right suddenly usable?

Because match matches patterns to the left of the => in each arm. It can unpack tuples, match struct fields, borrow parts of a value, etc.

If I guessed right, what's the difference of Ok(num) and Ok(_)?

_ is a wildcard pattern and matches everything.

The difference between Ok(num) and Ok(_) is that in first case you are asking that if the Result is the Ok variant then store its value of type T in num. In the second case, you are saying that you do not care what value Ok holds — as long as the Result is the Ok variant you want to execute something.

Remember that when you use _ in a pattern, you cannot use _ inside the code i.e. this will not work because _ is not an identifier:

let guess: u32 = match guess.trim().parse() {
    Ok(_) => _,
    Err(_) => continue,
};
like image 189
sn99 Avatar answered Jan 07 '23 22:01

sn99