Почему я не могу использовать шаблон среза для фильтрации итератора окна? - PullRequest
1 голос
/ 08 октября 2019

У меня есть вектор чисел и я использую метод windows(2) для создания итератора, который дает мне соседние пары. Например, вектор [1, 2, 3] преобразуется в [1, 2], [2, 3]. Я хочу использовать метод find, чтобы найти фрагмент, который удовлетворяет определенному условию:

fn step(g: u64) -> Option<(u64, u64)> {
    let prime_list: Vec<u64> = vec![2, 3, 5, 7]; //For example
    if prime_list.len() < 2 {
        return None;
    }
    let res = prime_list.windows(2).find(|&&[a, b]| b - a == g)?;
    //...
    None
}

Я получаю сообщение об ошибке:

error[E0005]: refutable pattern in function argument: `&&[]` not covered
 --> src/lib.rs:6:43
  |
6 |     let res = prime_list.windows(2).find(|&&[a, b]| b - a == g)?;
  |                                           ^^^^^^^^ pattern `&&[]` not covered

Я не знаю, что это за ошибкаозначает: список не может содержать менее двух элементов, например. Может быть, параметр закрытия неправильный? Я пытался изменить это, но это ничего не изменило. a и b также правильно распознаются как u64 в моей IDE. Что здесь происходит?

1 Ответ

2 голосов
/ 08 октября 2019

Вы, программист, знаете, что каждое повторяющееся значение будет иметь длину 2, но откуда вы знаете, что ? Вы можете только сказать, что из прозаической документации функции:

Возвращает итератор для всех смежных окон размера длины. Окна перекрываются. Если срез короче размера, итератор не возвращает значений.

Нигде компилятор не знает эту информацию. Реализация Windows только утверждает, что итерированное значение будет срезом:

impl<'a, T> Iterator for Windows<'a, T> {
    type Item = &'a [T];
}

Я бы преобразовал срез в ссылку на массив, отбрасывая любые срезы, которые были неправильной длины (что, как вы знаете, не можетслучиться):

use std::convert::TryFrom;

fn step(g: u64) -> Option<(u64, u64)> {
    let prime_list: Vec<u64> = vec![2, 3, 5, 7]; // For example

    if prime_list.len() < 2 {
        return None;
    }

    let res = prime_list
        .windows(2)
        .flat_map(<&[u64; 2]>::try_from)
        .find(|&&[a, b]| b - a == g)?;
    //...
    None
}

См. также:

В качестве альтернативы вы можете использовать итератор целых чисел и разбить его на части.

См. Также:

В какой-то момент в будущем const generics может быть стабилизирован и позволит включать длину массива в вызов функциии тип возврата.

См. также:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...