How to accept both Vec<String> and Vec<str> as function arg in Rust
You can go for full generic, you don't need to force user to use a Vec
, better you can take a generic type that implement IntoIterator
that you just have to write that Item
implement Into<String>
, the syntax is somehow strange and logic. You need a second generic type to do it. I call I
the type that will be the iterator and T the Item type.
fn foo<S: Into<String>>(string: S) -> String {
string.into()
}
fn foo_many<I, T>(iter: I) -> Vec<String>
where
I: IntoIterator<Item = T>,
T: Into<String>,
{
iter.into_iter().map(Into::into).collect()
}
fn main() {
println!("{}", foo(String::from("bar")));
println!("{}", foo("baz"));
for string in foo_many(vec!["foo", "bar"]) {
println!("{}", string);
}
for string in foo_many(vec![foo("foo"), foo("baz")]) {
println!("{}", string);
}
}
This solve your problem and make your function even more generic.
This doesn't work because your iteration doesn't give you S
but &S
.
If you want to move the strings out of the vector, you must make it mutable and drain it:
fn foo_many<S: Into<String>>(mut strings: Vec<S>) -> Vec<String> {
strings.drain(..).map(|s| s.into()).collect()
}
playground