使用 trim_end_matches 作为闭包函数类型不匹配:预期签名 ... 找到 "for<'r> ..." 的签名

Type mismatch using trim_end_matches as closure function: expected signature ... found signature of "for<'r> ..."

我有下面的代码来计算忽略标点符号的字数。

use std::collections::HashMap;

fn word_count(words: &str) -> HashMap<String, u32> {
    let mut hm: HashMap<String, u32> = HashMap::new();
    words
        .split_whitespace()
        .map(|word| word.trim_end_matches(char::is_ascii_punctuation))
        .map(|word| {
            hm.entry(word.to_string())
                .and_modify(|val| *val += 1)
                .or_insert(0)
        });
    hm
}

但是编译器抱怨

error[E0631]: type mismatch in function arguments
 --> src/lib.rs:7:26
  |
7 |         .map(|word| word.trim_end_matches(char::is_ascii_punctuation))
  |                          ^^^^^^^^^^^^^^^^
  |                          |
  |                          expected signature of `fn(char) -> _`
  |                          found signature of `for<'r> fn(&'r char) -> _`
  |
  = note: required because of the requirements on the impl of `std::str::pattern::Pattern<'_>` for `for<'r> fn(&'r char) -> bool {std::char::methods::<impl char>::is_ascii_punctuation}`

我无法弄清楚错误的真正含义或我的用法与 trim_end_matches 文档中的用法有何不同:assert_eq!("123foo1bar123".trim_end_matches(char::is_numeric), "123foo1bar");

如错误所述,trim_end_matches 期望参数是一个接受 char 的函数,但 char::is_ascii_punctuation 通过引用获取其参数。

你可以只添加一个闭包来转换:

.map(|word| word.trim_end_matches(|c| char::is_ascii_punctuation(&c)))

char 上的大多数谓词方法(例如 is_alphanumerc)采用 self,但是,出于历史向后兼容性原因(参见 RFC comments),特定于 ASCII 的方法取 &self。对于非 ASCII 方法,您可以这样做,例如:

.map(|word| word.trim_end_matches(char::is_alphanumeric))