macshaggy
macshaggy

Reputation: 367

How do I pass a vector and return a vector of strings?

I'm trying to figure out what I need to do to pass a vector and return a vector of strings in order to solve the anagram exercise on exercism.io.

Here is the test that I'm trying to pass:

fn test_no_matches() {
    let inputs = ["hello", "world", "zombies", "pants"];
    let outputs: Vec<&str> = vec![];
    assert_eq!(anagrams_for("diaper", &inputs), outputs);
}

and here is what I have written so far:

pub fn anagrams_for<'a>(word: &str, inp: Vec<&'a str>) -> Vec<&'a str> {
    let mut out: Vec<&str> = vec![];
    let ref poss = *inp[1];
    out.push(poss);
    out
}

But the test fails to compile at &inputs, giving me this error:

error[E0308]: mismatched types
 --> src/lib.rs:4:39
  |
4 |     assert_eq!(anagrams_for("diaper", &inputs), outputs);
  |                                       ^^^^^^^
  |                                       |
  |                                       expected struct `std::vec::Vec`, found `&[&str; 4]`
  |                                       help: try using a conversion method: `(&inputs).to_vec()`
  |
  = note: expected struct `std::vec::Vec<&str>`
          found reference `&[&str; 4]`

I've read about references, borrowing, and lifetimes. I can honestly say that I am a bit confused about passing references around. I thought about the return vector as just a Vec<String> but I think there was an issue about the input vectors reference to a str that was causing the problems.

If anyone could push me in a better direction that would be appreciated as I don't want to Kirk the test.

Upvotes: 6

Views: 17659

Answers (2)

Shepmaster
Shepmaster

Reputation: 432159

Let's look at the compiler error:

error[E0308]: mismatched types
 --> src/lib.rs:4:39
  |
4 |     assert_eq!(anagrams_for("diaper", &inputs), outputs);
  |                                       ^^^^^^^
  |                                       |
  |                                       expected struct `std::vec::Vec`, found `&[&str; 4]`
  |                                       help: try using a conversion method: `(&inputs).to_vec()`
  |
  = note: expected struct `std::vec::Vec<&str>`
          found reference `&[&str; 4]`

See how the compiler points to where the error is occurring? The error message states that you should be passing a Vec<&str> (a vector of string slices), but instead you are passing a &[&str; 4] (a reference to an array of length four containing string slices). These two types are not the same!

To make your code work, you could transform the array into a vector:

anagrams_for("diaper", inputs.to_vec());

Or you could construct a vector to start with:

let inputs = vec!["hello", "world", "zombies", "pants"];
anagrams_for("diaper", inputs);

But both of those are silly because you are allocating a vector and never using any of the power that it gives you. Instead, you really just want to accept a slice of string slices:

fn anagrams_for<'a>(word: &str, inp: &[&'a str]) -> Vec<&'a str>

A reference to an array can be implicitly converted to a slice, as can a reference to a Vec, so accepting a slice is often the best choice, when it applies.

Upvotes: 5

WiSaGaN
WiSaGaN

Reputation: 48127

Just change your function signature from

pub fn anagrams_for<'a>(word: &str, inp: Vec<&'a str>) -> Vec<&'a str>

to

pub fn anagrams_for<'a>(word: &str, inp: &[&'a str]) -> Vec<&'a str>

&[T] can accept both v: Vec<T> and v: [T; n] as arguments by using &v.

Upvotes: 7

Related Questions