Reputation: 367
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
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
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