user160995
user160995

Reputation: 129

Why does a match never use the second match arm?

I am trying to make reimplementation of first 2 Final Fantasy games using original data from various platforms. I want to get 2 program arguments using the getopts crate and handle both of them by using match but it just executes the first match element. I think I screwed up something with types.

Maybe there is another way to do it? I am lost using the official Rust docs and any tutorials on internet are not really noob-friendly.

Here is the code:

let args: Vec<String> = env::args().map(|x| x.to_string()).collect();

if(args.len() < 3) {
    println!("=====ERROR=====\nInvalid number of parameters\nExpected: <gamename> <gamerom>\nType in: 'help me' to get some help.");
    process::exit(1);
}

let ref game = args[1];
let ref rom = args[2];

match game {
    help => {
        println!("=====HELP======");

        match rom {
            list => println!("Available games: ff1, ff2\nAvailable roms: ff1_j_msx, ff1_j_nes, ff1_u, ff1and2, ff2_j, ff2_u_proto"),
            me => println!("Available help commands:\nlist -> List of available games and roms.\nme -> This help"),
            _ => println!("=====ERROR=====\nInvalid help command.")
        }
    },
    _ => println!("=====ERROR=====\nInvalid game, type in 'help me' to get some help.") 
}

Upvotes: 0

Views: 332

Answers (1)

Shepmaster
Shepmaster

Reputation: 431589

You really need to read the compilers error and warning messages. This code has seven warnings. If you had addressed any of them you'd be a lot closer to fixing the problem yourself. If you'd fixed all of them, your problem would be gone.

Here's a representative warning where the compiler tells you exactly what the problem is:

warning: unreachable pattern
  --> src/main.rs:24:5
   |
24 |     _ => println!("=====ERROR=====\nInvalid game, type in 'help me' to get some help.")
   |     ^ this is an unreachable pattern
   |
   = note: #[warn(unreachable_patterns)] on by default
note: this pattern matches any value
  --> src/main.rs:15:5
   |
15 |     help => {
   |     ^^^^

When you use just help, that creates a new variable with the value you are matching on. In this case, it matches everything, so the subsequent arms can never match.

Instead, you need to match against a string literal:

match game.as_str() {
    "help" => {
        match rom.as_str() {
            "list" => /* ... */,
            "me" => /* ... */,
            _ => /* ... */,
        }
    },
    _ => /* ... */,
}

I'd strongly encourage you to go back and re-read The Rust Programming Language. It's where a lot of the beginner documentation is kept. Specifically, you should read from the beginning and then up through the chapter on match and the chapter on patterns.

Upvotes: 5

Related Questions