В <Iterator>против Итератора для онлайн-алгоритмов - PullRequest
0 голосов
/ 26 марта 2019

Я пишу сетевой алгоритм, реализованный с помощью ряда функций, которые принимают итераторы и создают итераторы.

Когда я пишу функцию примерно так (контент более сложный, но не отличается по типам):

fn decode<'a, T>(input: T) -> impl Iterator<Item = i16> + 'a
where
    T: Iterator<Item = &'a u8> + 'a,
{
    input.map(|b| i16::from(*b)).filter(|i| *i != 0)
}

См. детская площадка .

Однако это делает вызов функции неэргономичным:

let input: Vec<u8> = vec![1, 2, 3, 0];
let v: Vec<i16> = decode(input.iter()).collect();

Я бы предпочел использовать T: Into<Iterator<..., но не могу. Когда я пишу подпись таким образом:

fn decode<'a, T>(input: T) -> impl Iterator<Item = i16> + 'a
where
    T: Into<Iterator<Item = &'a u8>> + 'a,

детская площадка

Я получаю сообщение о том, что размер возвращаемого типа неизвестен во время компиляции:

error[E0277]: the size for values of type `(dyn std::iter::Iterator<Item=&'a u8> + 'static)` cannot be known at compilation time
 --> src/main.rs:1:1
  |
1 | / fn decode<'a, T>(input: T) -> impl Iterator<Item = i16> + 'a
2 | | where
3 | |     T: Into<Iterator<Item = &'a u8>> + 'a,
4 | | {
5 | |     input.into().map(|b| i16::from(*b)).filter(|i| *i != 0)
6 | | }
  | |_^ doesn't have a size known at compile-time
  |
  = help: the trait `std::marker::Sized` is not implemented for `(dyn std::iter::Iterator<Item=&'a u8> + 'static)`
  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
  = note: required by `std::convert::Into`

Почему это так, и есть ли лучший способ?

1 Ответ

4 голосов
/ 26 марта 2019

Используйте IntoIterator вместо:

fn decode<'a>(input: impl IntoIterator<Item = &'a u8> + 'a) -> impl Iterator<Item = i16> + 'a {
    input.into_iter().map(|b| i16::from(*b)).filter(|i| *i != 0)
}

Iterator - это черта, а черты не имеют размера.Вот почему вы не можете (пока) написать:

fn example(x: Iterator<Item = ()>) {}
error[E0277]: the size for values of type `(dyn std::iter::Iterator<Item=()> + 'static)` cannot be known at compilation time
 --> src/lib.rs:1:12
  |
1 | fn example(x: Iterator<Item = ()>) {}
  |            ^ doesn't have a size known at compile-time
  |
  = help: the trait `std::marker::Sized` is not implemented for `(dyn std::iter::Iterator<Item=()> + 'static)`
  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
  = note: all local variables must have a statically known size
  = help: unsized locals are gated as an unstable feature

Into определяется как:

pub trait Into<T> {
    fn into(self) -> T;
}

Что-то, что реализует Into<dyn Iterator>должна иметь функцию fn into(self) -> dyn Iterator, возвращающую черту.Поскольку у черты нет размера, ее нельзя (пока) вернуть, сохранить в переменной или принять в качестве аргумента.

См. Также:

...