Types 在匹配臂中创建闭包
我正在翻阅铁锈书,并且一直在修改“minigrep”项目,这样一来,我就没有了Types 在匹配臂中创建闭包,types,rust,pattern-matching,closures,boxing,Types,Rust,Pattern Matching,Closures,Boxing,我正在翻阅铁锈书,并且一直在修改“minigrep”项目,这样一来,我就没有了search和search\u case\u insensitive函数,而是有了一个search函数,该函数采用指定大小写敏感度的枚举。这就是我的作品: pub fn search<'a>(query: &str, contents: &'a str, case: &Case) -> Vec<&'a str> { match case {
search
和search\u case\u 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 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))
};
由于类型规则,以这种方式使用闭包不是一个好主意,还是我只是出于天真而错误地“装箱”了?过滤器闭包的类型必须是
FnMut(&Self::Item)->bool
,因为您有一个迭代器
因此&Self::Item
变成了&str
。因此,您应该使用Box bool
,而不是Box bool
:
enum案例{
敏感的
不敏感的
}
fn search Vec过滤器
闭包的类型必须是FnMut(&Self::Item)->bool
,因为您有一个迭代器
,&Self::Item
就变成了和&str
。因此,您应该使用Box bool
,而不是Box bool
:
enum案例{
敏感的
不敏感的
}
fn search Vec您非常接近。该错误是由于Iterator::filter()
将引用传递给Iterator提供的元素而导致的,因此如果您在&str
上进行迭代,则传递给filter
的闭包必须接受和&str
。只需将Box bool>
更改为Box bool>
即可修复要编译的示例
通过使用两个变量和一个动态引用,可以避免不必要的分配:
let case_sensitive_filter = |line: &&str| line.contains(query);
let case_insensitive_filter = |line: &&str| line.to_lowercase().contains(&query.to_lowercase());
let filter: &dyn Fn(&&str) -> bool = match case {
Case::Sensitive => &case_sensitive_filter,
Case::Insensitive => &case_insensitive_filter,
};
contents.lines().filter(filter).collect()
解决不兼容arms问题的另一种方法是创建单个闭包并检查闭包内的案例:
let filter = |line: &&str| match case {
Case::Sensitive => line.contains(query),
Case::Insensitive => line.to_lowercase().contains(&query_lower),
};
你很接近。该错误是由于Iterator::filter()
将引用传递给Iterator提供的元素而导致的,因此如果您在&str
上进行迭代,则传递给filter
的闭包必须接受和&str
。只需将Box bool>
更改为Box bool>
即可修复要编译的示例
通过使用两个变量和一个动态引用,可以避免不必要的分配:
let case_sensitive_filter = |line: &&str| line.contains(query);
let case_insensitive_filter = |line: &&str| line.to_lowercase().contains(&query.to_lowercase());
let filter: &dyn Fn(&&str) -> bool = match case {
Case::Sensitive => &case_sensitive_filter,
Case::Insensitive => &case_insensitive_filter,
};
contents.lines().filter(filter).collect()
解决不兼容arms问题的另一种方法是创建单个闭包并检查闭包内的案例:
let filter = |line: &&str| match case {
Case::Sensitive => line.contains(query),
Case::Insensitive => line.to_lowercase().contains(&query_lower),
};