我在Rust中有此函数,该函数将字符串大写。
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(),
}
}
稍后,我用它来遍历字符串向量。
let words = vec!["hello", "world"];
let capitalized_words: Vec<String> =
words.iter().map(|word| capitalize_first(word)).collect();
这按预期工作,但是我注意到闭包|word| capitalize_first(word)
几乎没有用。因此,我尝试通过直接传递capitalize_first
来代替它。
let words = vec!["hello", "world"];
let capitalized_words: Vec<String> = words.iter().map(capitalize_first).collect();
但是,它无法通过以下错误消息进行编译。
10 | pub fn capitalize_first(input: &str) -> String {
| ---------------------------------------------- found signature of `for<'r> fn(&'r str) -> _`
...
38 | let capitalized_words: Vec<String> = words.iter().map(capitalize_first).collect();
| ^^^^^^^^^^^^^^^^ expected signature of `fn(&&str) -> _`
我无法理解此错误。为什么闭包有效,但直接传递函数无效。有什么我可以更改的东西,可以让我传递函数引用而不是进行无用的关闭吗?
当您像调用words.iter()
那样遍历一个集合时,就遍历了对元素的引用。向量中的元素的类型为&str
,因此对元素的引用的类型为&&str
。
所以map
期望一个函数接受类型为&&str
的参数,因此这就是推断闭包中的word
参数的方式。然后,当您在capitalize_first
上调用word
时,由于为所有引用实现了&str
特性,它会自动取消引用到Deref
。
但是,尽管由于此转换,您的函数似乎将接受类型为Deref
的参数,但转换仍在函数外部进行。因此,这并不意味着可以传递您的函数代替期望&&str
的函数。
有2个解决方案。您可以将函数更改为更通用的功能,并使其接受实现&&str
的任何内容。然后它将接受任何可以取消引用到AsRef<str>
的内容,包括str
,&str
和&&str
等。
String
或者您可以通过在迭代器上调用
pub fn capitalize_first<S: AsRef<str>>(input: S) -> String { let mut c = input.as_ref().chars(); // Don't forget this ^ match c.next() { None => String::new(), Some(first) => first.to_uppercase().collect::<String>() + c.as_str(), } }
来保留其功能,并在调用站点处对其进行修复,这实际上将取消引用元素。
copied()
我建议第一种方法。