I'm not totally clear on your issue without seeing your code, but I had no problem implementing a "Last Optimized Iter", providing I could initialize it. The issue that gave me trouble was holding onto the "last" pointer inside the list object, and to solve that I had to use Rc pointers.
Here is the code I quickly threw together
struct List {
head : Option<Box<ListElement>>,
//last : & Option<Box<ListElement>> //Can't have self-referential structures without smart-pointers
}
struct ListElement {
element : u64,
next : Option<Box<ListElement>>
}
impl List {
fn new(first_element : u64) -> Self {
let head = ListElement{
element : first_element,
next : None
};
Self {head : Some(Box::new(head))}
}
}
struct LastOptimizedIter<'a> {
current : &'a Option<Box<ListElement>>,
last : &'a Option<Box<ListElement>>,
}
impl <'a>LastOptimizedIter<'a> {
fn new(list : &'a List) -> Self {
LastOptimizedIter {
current : &list.head,
last : &list.head //NOTE: This should be a last ptr stored with the list
}
}
}
impl <'a>Iterator for LastOptimizedIter<'a> {
type Item=u64;
fn next(&mut self) -> Option<u64> {
if let Some(current) = self.current {
let return_val = current.element;
self.current = ¤t.next;
Some(return_val)
} else {
None
}
}
fn last(self) -> Option<u64> {
if let Some(last) = self.last {
Some(last.element)
} else {
None
}
}
}
fn main() {
let list = List::new(1234);
let the_iter = LastOptimizedIter::new(&list);
for element in the_iter {
println!("{}", element);
}
let the_iter = LastOptimizedIter::new(&list);
println!("{}", the_iter.last().unwrap())
}
And here is the code with Rc instead of Box, and a List::push() function
use std::rc::Rc;
use core::cell::RefCell;
struct List {
head : Option<Rc<RefCell<ListElement>>>,
last : Option<Rc<RefCell<ListElement>>>
}
struct ListElement {
element : u64,
next : Option<Rc<RefCell<ListElement>>>
}
impl List {
fn new(first_element : u64) -> Self {
let head = ListElement{
element : first_element,
next : None
};
let head_ptr = Rc::new(RefCell::new(head));
Self {
head : Some(head_ptr.clone()),
last : Some(head_ptr)
}
}
fn push(&mut self, element : u64) {
let new_element = ListElement{
element : element,
next : None
};
let new_element_ptr = Rc::new(RefCell::new(new_element));
if let Some(current_last) = &self.last {
current_last.borrow_mut().next = Some(new_element_ptr.clone());
}
self.last = Some(new_element_ptr);
}
}
struct LastOptimizedIter {
current : Option<Rc<RefCell<ListElement>>>,
last : Option<Rc<RefCell<ListElement>>>,
}
impl LastOptimizedIter {
fn new(list : &List) -> Self {
LastOptimizedIter {
current : list.head.clone(),
last : list.last.clone()
}
}
}
impl Iterator for LastOptimizedIter {
type Item=u64;
fn next(&mut self) -> Option<u64> {
if let Some(current) = self.current.clone() {
let return_val = current.borrow().element;
self.current = current.borrow().next.clone();
Some(return_val)
} else {
None
}
}
fn last(self) -> Option<u64> {
if let Some(last) = self.last {
Some(last.borrow().element)
} else {
None
}
}
}
fn main() {
let mut list = List::new(1234);
list.push(5678);
let the_iter = LastOptimizedIter::new(&list);
for element in the_iter {
println!("{}", element);
}
let the_iter = LastOptimizedIter::new(&list);
println!("{}", the_iter.last().unwrap())
}
Anyway, as @jjpe said, using the built-in containers is always better if possible.
I also got a lot out of reading Introduction - Learning Rust With Entirely Too Many Linked Lists