croraf
croraf

Reputation: 4728

Implement Iterator in Rust

I'm making an iterator in rust. In the next() method I want to extract next_element as current_element which will be returned, and create new Term instance and set it as next_element:

pub struct Term {
    pub coefficient: f64,
    pub index: i32,
    pub exponent: f64,
}

pub struct SeriesIterator {
    next_element: Term,
}

impl Iterator for SeriesIterator {
    type Item = Term;
    fn next(&mut self) -> Option<Self::Item> {
        let current_element = self.next_element;
        self.next_element = Term {
            coefficient: 1.0,
            index: current_element.index + 1,
            exponent: f64::from(current_element.index + 1),
        };
        Some(current_element)
    }
}

How to move ownership of next_element into current_element which will finally be moved outside with the return of next()?

cannot move out of `self.next_element` which is behind a mutable reference
   |
   |     let current_element = self.next_element;
   |                          ^^^^^^^^^^^^^^^^

Upvotes: 2

Views: 222

Answers (1)

wasmup
wasmup

Reputation: 16253

  1. Using std::mem::replace, try this:
    fn next(&mut self) -> Option<Self::Item> {
        let index = self.next_element.index + 1;

        Some(std::mem::replace(
            &mut self.next_element,
            Term {
                coefficient: 1.0,
                index: index,
                exponent: f64::from(index),
            },
        ))
    }

  1. Using #[derive(Clone, Copy)]:
    fn next(&mut self) -> Option<Self::Item> {
        let current_element = self.next_element; // copy

        self.next_element.coefficient = 1.0;
        self.next_element.index += 1;
        self.next_element.exponent = f64::from(self.next_element.index);

        Some(current_element)
    }

Try this working example:


#[derive(Clone, Copy)]
pub struct Term {
    pub coefficient: f64,
    pub index: i32,
    pub exponent: f64,
}
pub struct SeriesIterator {
    next_element: Term,
}

impl Iterator for SeriesIterator {
    type Item = Term;
    fn next(&mut self) -> Option<Self::Item> {
        let current_element = self.next_element; // copy

        self.next_element.coefficient = 1.0;
        self.next_element.index += 1;
        self.next_element.exponent = f64::from(self.next_element.index);

        Some(current_element)
    }
}

fn main() {
    let mut t = SeriesIterator {
        next_element: Term {
            coefficient: 1.0,
            index: 0,
            exponent: 1.0,
        },
    };

    let next = t.next().unwrap();
    println!("{}", next.index); // 0
    println!("{}", t.next_element.index); // 1

    let next = t.next().unwrap();
    println!("{}", next.index); // 1
    println!("{}", t.next_element.index); // 2
}

Output:

0
1
1
2

Upvotes: 2

Related Questions