Несоответствие типов с использованием trim_end_matches в качестве функции закрытия: ожидаемая подпись ... найдена подпись "for <'r> ..." - PullRequest
1 голос
/ 18 марта 2019

У меня есть код ниже для подсчета слов, в котором пунктуация игнорируется.

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

1 Ответ

3 голосов
/ 18 марта 2019

Как говорит ошибка, 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 ), специфичные для ASCII методы принимают &self. Для не-ASCII методов вы можете просто сделать, например:

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