Types 在匹配臂中创建闭包

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 {

我正在翻阅铁锈书,并且一直在修改“minigrep”项目,这样一来,我就没有了
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),
};