3

I'm relatively new to Rust and am trying to do the following:

pub fn route(request: &[String]) {
    let commands = ["one thing", "another thing", "something else"];

    for command in commands.iter() {
        if command == request {
            // do something
        } else {
            // throw error
        }
    }
}

When I try to build this, I get a compiler error:

error[E0277]: the trait bound `&str: std::cmp::PartialEq<[std::string::String]>` is not satisfied
 --> src/main.rs:5:20
  |
5 |         if command == request {
  |                    ^^ can't compare `&str` with `[std::string::String]`
  |
  = help: the trait `std::cmp::PartialEq<[std::string::String]>` is not implemented for `&str`
  = note: required because of the requirements on the impl of `std::cmp::PartialEq<&[std::string::String]>` for `&&str`
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • 1
    Your example tries to compare a single string to an array of strings. The problem has nothing to do with `str` vs. `String`. – mcarton Jan 07 '18 at 16:04

1 Answers1

5

You should go back and re-read The Rust Programming Language, specifically the chapter on strings. String and &str are two different types.

You can create Strings in a number of ways, but I commonly use String::from:

let commands = [
    String::from("one thing"),
    String::from("another thing"),
    String::from("something else"),
];

However, this is inefficient as you are allocating memory each time. It's better to instead go the other way, from &String to &str. Additionally, this doesn't solve your problem because you are attempting to compare a single value to a collection. We can solve both at once:

let commands = ["one thing", "another thing", "something else"];

for command in commands.iter() {
    if request.iter().any(|r| r == command) {
        // do something
    } else {
        // throw error
    }
}

See also:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • 1
    super helpful, makes total sense, and compiled perfectly. thanks a ton my dude – Cassandra O'Connell Jan 07 '18 at 16:12
  • 1
    @CassandraO'Connell Since you probably want to dispatch based on the command, it will likely be more useful to have a hash map mapping the command name to a function pointer or an integer id. Otherwise you will still need to compare `command` to each possible value, making the array of commands somewhat useless. – Sven Marnach Jan 07 '18 at 16:21
  • @SvenMarnach for a smaller, static set of items, I'd probably [just use a `match`](https://play.rust-lang.org/?gist=c91e74868f1e1622087841c0a2a29db7&version=stable). Creating a `HashMap` has that allocation overhead which we can avoid for a little while longer. – Shepmaster Jan 07 '18 at 16:29