Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Does Rust shadow variables that are not re-declared?

I am trying to learn Rust, and am trying to write a simple program that takes arguments from the command line, to get used to some basic concepts. The code I wrote to handle the arguments, fails, and I feel like I am missing some basic concept.

fn process_args(args: Vec<String>) {
    let my_string: String = String::from("--verbose");
    for item in &args[1..]    {
        match item{
            my_string=>do_something_with_argument(),
            _=>println!("unexpected argument {item}"),
        }
    }
}

Where vscode tells me that the ‘my_string’, variable is unused.
I also tried this version:

fn process_args(args: Vec<String>) {
    for item in &args[1..]    {
        match item{
            "--verbose"=>do_something_with_argument(),
            _=>println!("unexpected argument {item}"),
        }
    }
}

which fails because the string literal cannot be matched with a string, then I tried:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

fn process_args(args: Vec<String>) {
    for item in &args[1..]    {
        match item{
            String::from("--verbose")=>do_something_with_argument(),
            _=>println!("unexpected argument {item}"),
        }
    }
}

Which also does not work.

What am I missing. I feel like they all should work.

>Solution :

The left hand side of a "match" arm is a pattern. If you have a name in a pattern, it’s an implicit declaration. So in the first version, the first arm is just a pattern for any value, binding it to the (new) local variable my_string. Some languages (e.g. erlang) can dereference variables in patterns, Rust can’t.

The third version can not work, because a function call is not a valid pattern.

The second version actually nearly works if you bother to read the compiler error:

error[E0308]: mismatched types
 --> src/lib.rs:4:13
  |
3 |         match item {
  |               ---- this expression has type `&String`
4 |             "--verbose" => {},
  |             ^^^^^^^^^^^ expected `&String`, found `&str`
  |
  = note: expected reference `&String`
             found reference `&'static str`

item is an &String, but the pattern only matches &str, so all you need to do is make the two match by "converting" item to an &str, via String::as_str or &** for instance:

fn process_args2(args: Vec<String>) {
    for item in &args[1..]    {
        match &**item {
            "--verbose" => {},
            _=>println!("unexpected argument {item}"),
        }
    }
}

Although I would also say that this is not very useful, you’re testing flags for equality, why don’t you just… test flags for equality? Using ==? It’s not like Rust can construct a jump table from strings.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading