Bläddra i källkod

Midway through chapter 4

master
Lachlan Jacob 5 år sedan
förälder
incheckning
8806644b05
3 ändrade filer med 108 tillägg och 3 borttagningar
  1. 8
    2
      NOTES.md
  2. 98
    0
      lists/src/fourth.rs
  3. 2
    1
      lists/src/lib.rs

+ 8
- 2
NOTES.md Visa fil

Sometimes you just have to get your hands dirty and do some lifetimes, just a fact of life, get used to it son. Sometimes you just have to get your hands dirty and do some lifetimes, just a fact of life, get used to it son.
Revise some of these impl types, to understand better how they function with std library collections. Revise some of these impl types, to understand better how they function with std library collections.


# Lessons from Persistent Stack
# Lessons from Stack 3


and_then(<closure>) allows you to map over a value returning an option. and_then(<closure>) allows you to map over a value returning an option.
Useful for when the type mapping is an option.
Useful for when the type mapping is an option.

# Lessons from Stack 4

It's important to conceptualise the invariants before you write code to validate assumptions and edge cases.
borrow() and borrow_mut() are important methods when using RefCell.
Drop can be implemented with `popping` until no elements are left.

+ 98
- 0
lists/src/fourth.rs Visa fil

use std::rc::Rc;
use std::cell::RefCell;

pub struct List<T> {
head: Link<T>,
tail: Link<T>,
}

type Link<T> = Option<Rc<RefCell<Node<T>>>>;

struct Node<T> {
elem: T,
next: Link<T>,
prev: Link<T>,
}

impl<T> Node<T> {
fn new(elem: T) -> Rc<RefCell<Self>> {
Rc::new(RefCell::new(Node {
elem,
prev: None,
next: None,
}))
}
}

impl<T> List<T> {

pub fn new() -> Self {
List { head: None, tail: None }
}

pub fn push_front(&mut self, elem: T) {
let new_head = Node::new(elem);
match self.head.take() {
Some(old_head) => {
old_head.borrow_mut().prev = Some(new_head.clone());
new_head.borrow_mut().next = Some(old_head);
self.head = Some(new_head);
}
None => {
self.tail = Some(new_head.clone());
self.head = Some(new_head);
}
}
}

pub fn pop_front(&mut self) -> Option<T> {
self.head.take().map(|old_head| {
match old_head.borrow_mut().next.take() {
Some(new_head) => {
new_head.borrow_mut().prev.take();
self.head = Some(new_head);
}
None => {
self.tail.take();
}
}
Rc::try_unwrap(old_head).ok().unwrap().into_inner().elem
})
}
}

impl<T> Drop for List<T> {
fn drop(&mut self) {
while self.pop_front().is_some() {}
}
}

#[cfg(test)]
mod test {
use super::List;

#[test]
fn basics() {
let mut list = List::new();

assert_eq!(list.pop_front(), None);

list.push_front(1);
list.push_front(2);
list.push_front(3);

assert_eq!(list.pop_front(), Some(3));
assert_eq!(list.pop_front(), Some(2));

list.push_front(4);
list.push_front(5);

assert_eq!(list.pop_front(), Some(5));
assert_eq!(list.pop_front(), Some(4));

assert_eq!(list.pop_front(), Some(1));
assert_eq!(list.pop_front(), None);
}
}



+ 2
- 1
lists/src/lib.rs Visa fil

pub mod first; pub mod first;
pub mod second; pub mod second;
pub mod third;
pub mod third;
pub mod fourth;

Laddar…
Avbryt
Spara