In my attempt to make my code a little bit cleaner, I tried passing the closure directly by name to the map() to an iterator for a &[&str]. map will need to iterate over &&str which is understandable but my closure only takes &str.
Code example:
fn capitalize_first(word: &str) -> String {
word.chars().next().unwrap().to_uppercase().to_string()
}
fn main() {
let cap_cap = |word: &&str| -> String {
word.chars().next().unwrap().to_uppercase().to_string()
};
let a = ["we", "are", "testing"];
let b = &a; // this is where this becomes interesting.
b.iter().map(|&x| capitalize_first(x)); // Works
b.iter().map(|x| capitalize_first(x)); // Works
b.iter().map(cap_cap); // That's what the compiler expects.
b.iter().map(capitalize_first); // fails to compile!
}
Compiler error:
error[E0631]: type mismatch in function arguments
--> src/main.rs:17:18
|
1 | fn capitalize_first(word: &str) -> String {
| ----------------------------------------- found signature of `for<'r> fn(&'r str) -> _`
...
16 | b.iter().map(capitalize_first); // fails to compile!
| ^^^^^^^^^^^^^^^^ expected signature of `fn(&&str) -> _`
A couple of questions:
- Why does this work
map(|x| capitalize_first(x))whilemap(capitalize_first)doesn't? What sort of magic happens behind the scenes in the first case? In my view, those should be identical. - Is there a reason on why rust can't transparently convert between
&&strand&str?