I've heard that fn x(argument:&str) is recommended over fn x(argument:&String) because rust can coerce strings into &str
And that it can do the same for &Vec -> &
But when I try to combine them I get an error. I get that I'm trying to coerce String into &str (rather than &String into &str) which isn't allowed, but what's the recommended way of handling this in a way that maximizes genericity? Is there a way to tell rust I want to borrow what's inside the vector, not own it? I looked at the std::vec::Vec documentation and I don't see a .as_borrowed() method.
If Rust had function overloading I could just make a constructor that would borrow the innards and then pass it along, but it doesn't. Is there a String trait I can use to do this with generics?
This applies only to the outermost type. Vec<String> → &[String]
The type can't be coerced recursively, because each element of [String] takes 3 usize, and each element of [&str] takes 2 usize, so they're physically incompatible in memory.
It works for one String, because the first two fields of String are same as str, so it's possible to give pointer to String and have user of str ignore the extra data after it. It doesn't work for arrays, because the data after it is interpreted as the next element.
If you really need this flexibility, then taking impl IntoIterator<Item=impl AsRef<str>> is the most universal (you will have to call into_iter() and as_ref()).
It's not so much about need as best practice. It seems akward to make people who want to pass you strings build a pre-iterator just to improve genericity.
fn main() {
let vector: Vec<String> = vec!["a".to_string(),"b".to_string(),"c".to_string()];
// === preprocessor ===
// it's akward to make someone do this who wants to use your crate
let mut preprocessed: Vec<&str> = Vec::new();
for string in vector.iter(){
preprocessed.push(string);
}
// === preprocessor ===
test(&preprocessed);
}
fn test(something:&[&str]){
println!("{:?}",something);
}
I don’t think placement of fields inside String is relevant. &str is a (manufactured) fat ptr whose data and len components could’ve come from anywhere, they don’t need to point at contiguous data (the len isn’t a ptr anyway, just a usize).
The short version is vector.iter().map(|s| s.as_str()).collect().
It's simply physically impossible to use [String] as [&str] without copying. ABCABCABC data can't be used where ABABAB is expected. That's regardless of the language. In C it wouldn't work either.
Fundamentally I just want to make it as easy as possible for other people to use my functions and to maximize their genericity. letting fn x(a:&str) take in an &String and an &str seems reasonable and useful, but it seems difficult to follow that same pattern into the contents of Vecs / Arrays.
Here is the fixed variant. If you want to print the whole slice you need to add Debug bound. (btw with it you can print thing directly without conversion) Plus before converting to String first you have to explicitly get &str via as_ref. (Or you could use Deref bound instead of AsRef if you want to utilize automatic coercion)