Confusion around `Ok(num)` pattern in guessing game example (Rust Book)

I'm new to rust and learning the language via the The Rust Programming Language book ( stable version ) and following the Programming a Guessing Game chapter and I got confused in this part:

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

here when I type Ok(num) my IDE zed gives suggestions to import some external items/traits related to num, which confused me on the first time as I thought that the code example in the book is missing an import, but when I tinker with the name num then I realise that it is just a placeholder name, and we can use any name instead of num.

This might be quite confusing for someone who is new to the language and learning for the first time, It wasn’t immediately obvious that num is not something predefined or requiring an import.

Maybe we can explicitly mention it in the docs, that name like num in Ok(num) is just a placeholder name and you can use any name instead of num, so that new people like me does not confuse with the IDE suggestions.

Instead of opening the issue directory to the docs repo for this, I think to discuss it here and get some suggestions of other community members or if others had similar confusion and if there’s a better way to interpret this as a beginner.

It does not require an import. You either forgot to paste part of the code example or your IDE hallucinated.

What's going on in that code snippet is called pattern matching. You can learn more about it here.

In general if your IDE is being confusing when things don't compile, I suggest running cargo check (or cargo build) in a terminal to see the full warning and error output. Most IDEs truncate the errors, and sometimes they do a poor job of it to boot.

In this case,[1] the error is about a missing expression, with nothing being said about name resolution. So I too suspect the specific suggestion in question is probably an IDE problem more than anything.


Currently the book says

If parse is able to successfully turn the string into a number, it will return an Ok value that contains the resultant number. That Ok value will match the first arm’s pattern, and the match expression will just return the num value that parse produced and put inside the Ok value. That number will end up right where we want it in the new guess variable we’re creating.

And I do think it could be more explicit that the num in Ok(num) is introducing a new variable, similarly to how let guess does. (At a skim, the match examples before this point do not bind any variables.)


  1. based on the code screenshot ↩︎

I think you're missing the point. OP is saying num is a poor choice for a variable name, because it happens to be spelled the same as a standard library module, which could cause confusion for beginners.

Not really. It is true that my reply didn't address the point about the variable name, but that's because this is an XY situation and instead tried to address the real problem the OP is facing.

As quinedot demonstrated with the reproduced example in playground, the real problem is a compilation error caused by the compiler expecting an expression that is not there. That's why I instead tried to address the OP by saying that this kind of issues usually arise because people forgot to copy a line or two from the code example they were following, which trigger a compilation error, which can trigger IDEs to hallucinate...

If we go the route of "num being a poor choice for a variable name and this needs to be addressed in the book because it can confuse beginners", that's very easy to dismiss. You can't be defensive about variable names shadowing names of other things, specially when problems as the once faced by the OP only arise in very specific circumstances. Naming variables is a VERY prevalent thing we do when we write code; the least thing I think anyone would want is to read a book that is constantly warning the reader that any given variable name is just a placeholder name, and that they could use any name instead of the one chosed by the author(s).

The OP is explicitly asking to make things easier for beginners, who can easily feel insecure because of an overeager (and possibly faulty) IDE.

Choosing identifiers that do not trigger the IDE is the difference between very good and excellent learning material.

I don’t see how this isn’t anything but needlessly/overly dismissive.

The point brought up by OP was that they: “thought that the code example in the book is missing an import, but when I tinker with the name num then I realise that it is just a placeholder name, and we can use any name instead of num”. Now you come and say “you can’t be defensive about variable names shadowing names of other things”. This is assuming (incorrectly) that it’s clear to the reader that num here is supposed to be a newly introduced, arbitrarily chosen variable name. The book does not explain this at this point. This is the very first time the book presents a match statement that binds fields to variables. I don’t thing there’s any situation where *choosing a name that’s obviously arbitrarily chosen would be any more relevant than this one.

So this is IMHO (quite clearly) among the most important places in the book to choose a good variable name (that’s clearly presenting to be an arbitrary variable name). But you say little to address this point beyond “that’s very easy to dismiss” and then moving on to talking about shadowing. (In my view shadowing is quite irrelevant here, since shadowing is only a follow-up discussion to be had after the realization that there’s a variable being introduced here in the first place).


Edit: Speaking of shadowing, one not-unreasonable[1] choice of name here would actually be guess.

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

though realistically, I’d probably prefer a single-letter variable name (since that also very clearly signals “user-chosen”/arbitrary, and there’s no better place for single-letter names than when the section of code where the name is in scope is literally as short as 1 character.

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

If rewritten today, I’m wondering if the newer alternative of let-else could be demonstrated here, since

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

is quite reduced to

        let Ok(guess) = guess.trim().parse::<u32>() else {
            continue;
        };

but I’d concede that’s probably introducing too much new syntax at once.


  1. Not-unreasonable in terms of being idiomatic. It might be very much unreasonable in terms of being useful for teaching purposes here. ↩︎

Fair point. I focused my reply solely on the naming of the variable, since quinedot had already addressed how could the introduction of the new variable be improved in the book here:

I wasn't dismissing OPs entire concern. Again, I explicitly focused on the part of the naming of the variable.