作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在阅读 Rust Book 并一直在调整“minigrep”项目,这样我就没有同时拥有 search
和 search_case_insensitive
功能,而是拥有一个 search
函数,它采用指定区分大小写的枚举。这就是我所拥有的:
pub fn search<'a>(query: &str, contents: &'a str, case: &Case) -> Vec<&'a str> {
match case {
Case::Sensitive => contents
.lines()
.filter(|line| line.contains(query))
.collect(),
Case::Insensitive => {
let query = query.to_lowercase();
contents
.lines()
.filter(|line| line.to_lowercase().contains(&query))
.collect()
}
}
}
我想我会尝试重写它,以使用闭包删除重复的逻辑。然而,这会导致各种类型检查问题。我的第一次尝试:
let query_lower = query.to_lowercase();
let filter = match case {
Case::Sensitive => |line| line.contains(query),
Case::Insensitive => |line| line.to_lowercase().contains(&query_lower)
};
我很快了解到不同的闭包具有不同的类型,即使它们具有相同的签名。我读到装箱关闭可能会有所帮助:
let filter: Box<dyn Fn(&str) -> bool> = match case {
Case::Sensitive => Box::new(|line| line.contains(query)),
Case::Insensitive => Box::new(|line| line.to_lowercase().contains(&query_lower))
};
这确实解决了 ARM 类型不匹配的 match
,但是现在 .filter
提示它的参数是不正确的类型,现在我陷入了困境:
error[E0277]: expected a `FnMut<(&&str,)>` closure, found `dyn for<'r> Fn(&'r str) -> bool`
--> src/lib.rs:27:17
|
27 | .filter(filter)
| ^^^^^^ expected an `FnMut<(&&str,)>` closure, found `dyn for<'r> Fn(&'r str) -> bool`
|
= help: the trait `FnMut<(&&str,)>` is not implemented for `dyn for<'r> Fn(&'r str) -> bool`
= note: required because of the requirements on the impl of `for<'r> FnMut<(&'r &str,)>` for `Box<dyn for<'r> Fn(&'r str) -> bool>`
以这种方式使用闭包是不是一个好主意,因为类型规则,或者我只是出于天真而错误地“装箱”了东西?
最佳答案
filter
闭包的类型必须是 FnMut(&Self::Item) -> bool
因为你有一个 Iterator<Item = &str>
&Self::Item
变成 &&str
.所以而不是 Box<dyn Fn(&str) -> bool>
你应该使用 Box<dyn Fn(&&str) -> bool
:
enum Case {
Sensitive,
Insensitive,
}
fn search<'a>(query: &str, contents: &'a str, case: &Case) -> Vec<&'a str> {
let query_lower = query.to_lowercase();
let filter: Box<dyn Fn(&&str) -> bool> = match case {
Case::Sensitive => Box::new(|line| line.contains(query)),
Case::Insensitive => Box::new(|line| line.to_lowercase().contains(&query_lower)),
};
contents.lines().filter(filter).collect()
}
这是有效的,因为所有 Fn
类型也是 FnMut
.
关于types - 在火柴臂中创建闭包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66050177/
我是一名优秀的程序员,十分优秀!