#Beginner implementing custom collections / iterators

17 messages · Page 1 of 1 (latest)

tribal jay
#

I'm new to rust and trying to implement some custom collections for practice.

I've mostly implemented this singly-linked list, but I'm not sure how to implement the iterator.
Currently I'm getting this (L106):

// cannot return value referencing temporary value
Some(ref r) => Some(&r.borrow().value),

I understand (basically) what it means, but not how to fix it.

#

just the iterator part:

pub struct Iter<'a, T: 'a> {
    _target: &'a AbsorbingSequence<T>,
    current: Option<Rc<RefCell<Node<T>>>>,
}

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = &'a T;

    fn next(&'a mut self) -> Option<Self::Item> {
        let current = self.current.take()?;
        self.current = current.borrow().next.as_ref().map(|rc| Rc::clone(rc));
        // self.current.as_ref().map(|r| {
        //     &(r.borrow().value)
        // })
        match self.current {
            None => None,
            // cannot return value referencing temporary value
            Some(ref r) => Some(&r.borrow().value),
        }
    }
}
#

I've updated next so it doesn't skip the first value, but it has the same problem:

fn next(&mut self) -> Option<Self::Item> {
    let prior = self.current.take()?;
    self.current = prior.borrow().next.as_ref().map(|rc| Rc::clone(rc));
    // cannot return value referencing local variable `prior`
    Some(&prior.borrow().value)
}
keen halo
tribal jay
#

oh neat, thanks!

wooden lynx
#

for a singly linked list, you don't really need Rc and RefCell, just a Box suffices. Rc makes sense for a doubly linked list, but it's inefficient.

tribal jay
#

I tried a version where nodes held a next: Box<Node<T>>, but I couldn't figure out a good way to give the list a reference to the tail node (in addition to owning the head node)
I had this:

struct Ends<'a, T> {
    head: Node<T>,
    tail: &'a Node<T>,
}

impl<'a, T> Ends<'a, T> {
    fn new(node: Node<T>) -> Ends<'a, T> {
        Ends {
            head: node,
            // Value used after being moved
            tail: &node,
        }
    }
}

basically idk how to initialize a struct with a reference to a value it owns, because when I need to create the reference, it doesn't own the value yet

I could make it tail: Option<&'a Node<T>> and immediately fill it afterward, but having an Option that's Some except during initialization isn't ideal

grave mist
#

I tried a version where nodes held a next: Box<Node<T>>, but I couldn't figure out a good way to give the list a reference to the tail node

basically idk how to initialize a struct with a reference to a value it owns,

#

you cannot do this

#

or rather, if you try, you will end up having a nearly useless struct that borrows itself forever

#

do not build data structures out of references (unless you know exactly what you are doing)

tribal jay
#

is there a safe way to have a linked list with both tail and head access without something like Rc?

grave mist
#

no

#

you only get to share a thing (the tail) between two owners (head field, indirectly, and tail field, directly,) if you choose some form of sharing, like Rc or & (and & is not appropriate for this application)

#

if I were writing a linked list type for practice, I would write a strictly singly linked list

#

that is, one which has no idea what its tail is except by going and looking through the entire list

keen halo