rust - 使用 iter.map,为什么闭包可以工作,但直接传递函数却不行?
问题描述
我在 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()
,您正在遍历对元素的引用。向量中的元素是 type &str
,因此对元素的引用是 type &&str
。
所以map
期待一个接受 type 参数的函数,&&str
这就是word
你的闭包中的参数被推断为。然后,当您调用capitalize_first
时word
,它会自动取消引用到&str
,因为Deref
所有引用都实现了该特征。
但是,即使&&str
由于此转换,您的函数似乎会接受类型参数,但转换发生在您的函数之外。所以这并不意味着你的函数可以代替期望的函数传递&&str
。
有2个解决方案。您可以将函数更改为更通用,并让它接受任何实现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()
迭代器在调用站点修复它,这实际上将取消对元素的引用。
let capitalized_words: Vec<String> = words.iter().copied().map(capitalize_first).collect();
我会推荐第一种方法。
推荐阅读
- loops - 复制 EDL 的部分内容,计算持续时间但循环失败
- postgresql - Postgresql 将字符串值解析为整数
- api - 可以通过 API 密钥从前端进行 Google Cloud Text-to-Speech API 身份验证吗?
- powershell - 如何从脚本位置复制包含子文件夹和项目的文件夹?
- spring-boot - 在 Spring Boot 中为 postgresql 自定义更新和删除查询
- python - 如何从图像中提取不同边缘强度的矩形?
- html - 使用 ng-style 向进度条添加动态样式
- android - 如何清除 ChromeCustomTabs 中的 cookie?
- bash - 将 nmap 结果分配给 bash 中的数组
- javascript - 如何使用按钮 onclick 功能在画布内插入文本?