Match with Ok() Err() doesn't work

Why these code doesn't work

use std::io;


fn main() {
  let mut birthmonth: u32 = 0;

  loop {
    println!("Please enter your birthmonth >>");
    let mut user_birthmonth: String = String::new();
    io::stdin()
    .read_line(&mut user_birthmonth)
    .expect("Something went wrong");

    let user_birthmonth: u32 = match user_birthmonth.trim().parse() {
      Ok(num) if num <= 12 && num > 0 => num,
      Err(month) => 
        match month {
          "january" => 1,
          "february" => 2,
          "march" => 3,
          "april" => 4,
          "may" => 5,
          "june" => 6,
          "july" => 7,
          "august" => 8,
          "september" => 9,
          "october" => 10,
          "november" => 11,
          "december" => 12,
          _ => {
            println!("Please enter a valid birthmonth!");
            continue;
          },
        },
    };

    birthmonth = user_birthmonth;
    break;
  };

}

What do you exactly mean by "doesn't work"?

I mean error, just try run the code you'll see the error

I don't think you get the point. You have already run the code. Therefore, you can also tell me what the error is. That saves me the effort to open an editor, paste in the code, compile it and then run it.

3 Likes

Okay, wait

This is the error message

  1. let user_birthmonth: u32 = match user_birthmonth.trim().parse() {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected &str, found struct ParseIntError

The month in Err(month) is a description of the issue with parsing, not the input to parse.
So write
match user_birthmonth.trim() { ...

Still error though

Here's a playground to a version that compiles: Rust Playground.

For the Err(month) case, month was bound to a ParseIntError (like previously pointed out by @MichaelV). but you were using it in a match that had patterns expecting a &str.

  Err(month) =>
        match month {
          "january" => ...

The next error was that the original match was not exhaustive. There were cases for Ok(num) for a range of num as well as Err(..) but needed a case for Ok(num) when num did not fall into that range.

To fix that, I included the third case with the Error case:

Ok(_) | Err(_) => 

This will match a successful parse that fails the guard you have set up in the other case (num <= 12 && num > 0 and it will also match a parse error.

2 Likes

// It's work fine but still with one warning

// How to get rid of this warning?

let mut birthmonth: u32 = 0;
| ^^^^^^^^^^
|
= note: #[warn(unused_assignments)] on by default
= help: maybe it is overwritten before being read?

warning: 1 warning emitted

Side-note: Learn to (read and) post the whole warning/error message. The full warning in this case is

warning: value assigned to `birthmonth` is never read
 --> src/lib.rs:5:11
  |
5 |   let mut birthmonth: u32 = 0;
  |           ^^^^^^^^^^
  |
  = note: `#[warn(unused_assignments)]` on by default
  = help: maybe it is overwritten before being read?

The first line that you were missing is the most important one, as it's the main part of the warning message.

If your IDE doesn't show you the warning properly, take it from the terminal as returned by cargo check.


Resolving this warning can be done by removing the = 0 part assigning the unused initial value.

let mut birthmonth: u32;

In consequence, the mut might become redundant, too.

Another possible alternative is to use a break with value, and do

let birthmonth: u32 = loop {
  ....
  break user_birthmonth;
};
1 Like