Добрый день,
В моей задаче необходимо, чтобы функция принимала как обычный std::iter::Iterator так и std::iter::Take.
Код:
use std::iter;
use std::slice;
fn f1(iter: &mut slice::Iter<u8>) {
iter.next();
}
fn f2(iter: &mut iter::Take<&mut slice::Iter<u8>>) {
iter.next();
}
fn main() {
let a = vec![0u8;10];
let mut i = a.iter();
f1(&mut i);
{
let ref mut iref = i;
f2(&mut iref.take(2));
}
println!("{:?}", i.as_slice());
}
Нужно сделать так, чтобы вместо f1 и f2 была одна функция.
Пробовал использовать Generic параметры, но ничего не вышло.
Это вообще возможно сделать?
Спасибо, но такой вариант не учитывает, что я использую итератор по u8.
Например так работать не будет:
fn f3<I: Iterator>(iter: &mut I) {
if let Some(x) = iter.next() {
println!("{:?}", *x);
}
}
https://play.rust-lang.org/?gist=da15a44325cfc36fed8793a5e72ded74&version=stable&backtrace=0
Спасибо, окончательный вариант вышел такой, так как хотелось бы ограничить тип, по которому создан итератор:
use std::iter::Iterator;
fn f3<'a, I: Iterator<Item = &'a u8>>(iter: &mut I) {
if let Some(x) = iter.next() {
println!("{:?}", *x);
}
}
fn main() {
let a = vec![0u8;10];
let mut i = a.iter();
f3(&mut i);
{
let ref mut iref = i;
f3(&mut iref.take(2));
}
println!("{:?}", i.as_slice());
}
Хм, попробовал использовать рекурсию для этой функции и получил ошибку:
<anon>:3:1: 9:2 error: reached the recursion limit during monomorphization
<anon>:3 fn f3<'a, I: Iterator<Item = &'a u8>>(iter: &mut I) {
<anon>:4 if let Some(x) = iter.next() {
<anon>:5 println!("{:?}", *x);
<anon>:6 }
<anon>:7
<anon>:8 f3(&mut iter.take(1));
https://play.rust-lang.org/?gist=99d8e25e06322b0778ce0ba5f5cf34bc&version=stable&backtrace=0
Кроме того как перейти на цикл, это никак нельзя исправить?
В реальной задаче я хотел бы передавать в f3() часть значений перебираемых итератором, поэтому пытаюсь ограничить кол-во с помощью take().
kstep
21.Июнь.2016 06:09:28
7
Можно использовать динамическую диспетчеризацию. fn f(iter: &mut Iterator<Item=u8>)
Тоже смотрю в сторону динамической диспетчеризации, но пока не осилил написать рабочий вариант.
kstep
21.Июнь.2016 07:44:01
9
Тут в случае рекурсии никак по другому не сделать, у тебя получается в результате мономорфизации куча функций вида f<Take<Take<Take<...>>>
с постоянно увеличивающейся глубиной типа, отсюда и ошибка с превышением рекурсии.
Спасибо, все получилось с динамической диспетчеризацией (почему-то я считал, что она обязательно связана с Box<T>
).
На всякий случай финальный вариант кода:
use std::iter::Iterator;
fn f3(iter: &mut Iterator<Item = &u8>) {
if let Some(x) = iter.next() {
println!("{:?}", *x);
}
else {
return;
}
f3(&mut iter.take(1));
}
fn main() {
let a = vec![0u8;10];
let mut i = a.iter();
f3(&mut i);
println!("{:?}", i.as_slice());
}
kstep
21.Июнь.2016 10:37:21
11
Box<Trait>
нужен, если нужно передать владение трейт-объектом. Если владения передавать не надо, можно обойтись &Trait
или &mut Trait
, как в данном случае.