使用trim_end_matches作为闭包函数键入不匹配:预期签名...找到“for ...”的签名

问题描述 投票:1回答:1

我有下面的代码来做一个字数统计,其中忽略标点符号。

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");

rust char ascii predicate
1个回答
3
投票

正如错误所说,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))
© www.soinside.com 2019 - 2024. All rights reserved.