Rustlings "iterators2" & Function Passing

In the Rustlings tutorial "iterators2", we have a capitalize_first function like this:

pub fn capitalize_first(input: &str) -> String {
    let mut c = input.chars();
    match c.next() {
        None => String::new(),
        Some(first) => first.to_uppercase().collect::<String>() + c.as_str(),
    }
}

And we're asked to map it over a vector, which can be accomplished by using a closure:

    let words = vec!["hello", "world"];
    let capitalized_words: Vec<String> = words.iter().map(|w| capitalize_first(w)).collect();
    assert_eq!(capitalized_words, ["Hello", "World"]);

This works, but I also tried the code:

   words.iter().map(capitalize_first).collect();

Which does not compile, and gives an error message I don't really understand: "expected signature of fn(&&str) -> _". In other programming languages I am familiar with, these two pieces of code would be identical. Why am I not allowed to pass the function name directly as an argument?

1 Like

This is because in the closure, deref coercion turns the &&str into a &str. This will work:

words.iter().map(|s| *s).map(capitalize_first).collect();
// or equivalently
words.iter().copied().map(capitalize_first).collect();

Deref coercion is the same as what turns &String into &str when you call such a function with a &String.

1 Like

If you don't need words afterwards, you can also move it by using into_iter - in this case the iterator will yield the values of the same type as the values in vector, i.e. &str. Check this playground.

2 Likes

You are. Please read the error message carefully, and check the documentation for iter(). What's the type of &T when T = &str?

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.