Skip to content

Pre-RFC: Save and load state for Iterator #2558

@tuxzz

Description

@tuxzz

On my project, I recently found a problem that I can't implement a comfortable interface that do operation on Iterator directly using existing API.

/* not work because iterator state is changed after each operation */
pub fn do_operateion<'a, T, U>(input_iter: &mut T, output_iter: &mut U)
where
    T: Iterator<Item = &'a f32>,
    U: Iterator<Item = &'a mut f32>,
{
    let temp = input_iter.skip(2).map(...).sum();
    output_iter.step_by(2).zip(input_iter).for_each(|a, b| *a * temp);
    output_iter.skip(1).step_by(2).zip(input_iter).for_each(|a, b| *a * temp * 123.0);
}

Hence the idea of adding StateSavableIterator trait:

pub trait StateSavableIterator: Iterator {
    type IteratorState;

    fn save(&self) -> IteratorState;
    fn load(&mut self, state: &IteratorState) -> Self;
}

So that I can:

pub fn do_operateion<'a, T, U>(input_iter: &mut T, output_iter: &mut U)
where
    T: StateSavableIterator<Item = &'a f32>,
    U: StateSavableIterator<Item = &'a mut f32>,
{
    let input_init = input_iter.save();
    let out_init = output_iter.save();
    let temp = input_iter.load(input_init).skip(2).map(...).sum();
    output_iter.load(out_init).step_by(2).zip(input_iter.load(input_init)).for_each(|a, b| *a * temp);
    output_iter.load(out_init).skip(1).step_by(2).zip(input_iter.load(input_init)).for_each(|a, b| *a * temp * 123.0);
}

We don't have to pass &slice anymore! This trait benefits to writing more generic and readable API.

Metadata

Metadata

Assignees

No one assigned

    Labels

    T-libs-apiRelevant to the library API team, which will review and decide on the RFC.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions