Jeff White
Jeff White

Reputation: 43

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(_)?

Upvotes: 4

Views: 229

Answers (2)

sn99
sn99

Reputation: 941

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,
};

Upvotes: 9

Pan Ke
Pan Ke

Reputation: 579

short answer. patterns match can destruct structs, enums... see here

signature of parse is pub fn parse<F>(&self) -> Result<F, <F as FromStr>::Err>. There is a generic type F in it.

The compiler finds let guess: u32 =, and it infers that what you need is u32. So the F is u32 here.

Then the patterns match destructing extracts num from Ok<u32>

Upvotes: 0

Related Questions