【发布时间】:2021-05-09 00:31:51
【问题描述】:
我正在阅读 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))
};
这当然解决了 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>`
由于类型规则,以这种方式使用闭包不是一个好主意,还是我只是出于天真而错误地“装箱”了一些东西?
【问题讨论】:
标签: types rust pattern-matching closures boxing