瀏覽代碼

Midway through chapter 4

master
Lachlan Jacob 6 年之前
父節點
當前提交
8806644b05
共有 3 個檔案被更改,包括 108 行新增3 行删除
  1. 8
    2
      NOTES.md
  2. 98
    0
      lists/src/fourth.rs
  3. 2
    1
      lists/src/lib.rs

+ 8
- 2
NOTES.md 查看文件

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 查看文件

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 查看文件

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

Loading…
取消
儲存