25
Symmetric Cases
Everything we did for the front exists for the back, with head and tail swapped and next and prev swapped. The _mut peek variants are the same shape but call borrow_mut and return RefMut<T> instead of Ref<T>. Boilerplate, no new ideas.
-
push_back,pop_back,peek_back: text-substitute the front versions.headbecomestail,tailbecomeshead,nextbecomesprev,prevbecomesnext. Same code, mirrored.pub fn push_back(&mut self, elem: T) { let new_tail = Rc::new(RefCell::new(Node { elem, prev: None, next: None })); match self.tail.take() { Some(old_tail) => { old_tail.borrow_mut().next = Some(new_tail.clone()); new_tail.borrow_mut().prev = Some(old_tail); self.tail = Some(new_tail); } None => { self.head = Some(new_tail.clone()); self.tail = Some(new_tail); } } } pub fn pop_back(&mut self) -> Option<T> { self.tail.take().map(|old_tail| { match old_tail.borrow_mut().prev.take() { Some(new_tail) => { new_tail.borrow_mut().next.take(); self.tail = Some(new_tail); } None => { self.head.take(); } } Rc::try_unwrap(old_tail).ok().unwrap().into_inner().elem }) } - The
_mutpeek variants exist because mutable access through a RefCell is a different guard type.borrow_mut()returnsRefMut<'_, T>, which is exclusive.RefMut::mapprojects it the same wayRef::mapdoes for shared.use std::cell::RefMut; pub fn peek_back(&self) -> Option<Ref<T>> { self.tail.as_ref().map(|n| Ref::map(n.borrow(), |n| &n.elem)) } pub fn peek_front_mut(&mut self) -> Option<RefMut<T>> { self.head.as_ref().map(|n| RefMut::map(n.borrow_mut(), |n| &mut n.elem)) } pub fn peek_back_mut(&mut self) -> Option<RefMut<T>> { self.tail.as_ref().map(|n| RefMut::map(n.borrow_mut(), |n| &mut n.elem)) }