Browse Source

Third chapter done

master
Lachlan Jacob 5 years ago
parent
commit
059d2d1d42
3 changed files with 108 additions and 1 deletions
  1. 5
    0
      NOTES.md
  2. 2
    1
      lists/src/lib.rs
  3. 101
    0
      lists/src/third.rs

+ 5
- 0
NOTES.md View File

take() is handy, read more about this. take() is handy, read more about this.
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

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

+ 2
- 1
lists/src/lib.rs View File

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

+ 101
- 0
lists/src/third.rs View File

use std::rc::Rc;

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

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

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

impl<T> List<T> {
pub fn new() -> Self {
List { head: None }
}
pub fn append(&self, elem: T) -> List<T> {
List { head: Some(Rc::new(Node {
elem,
next: self.head.clone(),
}))}
}
pub fn tail(&self) -> List<T> {
List { head: self.head.as_ref().and_then(|node| node.next.clone()) }
}
pub fn head(&self) -> Option<&T> {
self.head.as_ref().map(|node| &node.elem )
}
}

pub struct Iter<'a, T> {
next: Option<&'a Node<T>>,
}

impl<T> List<T> {
pub fn iter(&self) -> Iter<'_, T> {
Iter { next: self.head.as_ref().map(|node| &**node) }
}
}

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

fn next(&mut self) -> Option<Self::Item> {
self.next.map(|node| {
self.next = node.next.as_ref().map(|node| &**node);
&node.elem
})
}
}

impl<T> Drop for List<T> {
fn drop(&mut self) {
let mut head = self.head.take();
while let Some(node) = head {
if let Ok(mut node) = Rc::try_unwrap(node) {
head = node.next.take();
} else {
break;
}
}
}
}

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

#[test]
fn basics() {
let list = List::new();
assert_eq!(list.head(), None);

let list = list.append(1).append(2).append(3);
assert_eq!(list.head(), Some(&3));

let list = list.tail();
assert_eq!(list.head(), Some(&2));

let list = list.tail();
assert_eq!(list.head(), Some(&1));

let list = list.tail();
assert_eq!(list.head(), None);

// Make sure empty tail works
let list = list.tail();
assert_eq!(list.head(), None);

}

#[test]
fn iter() {
let list = List::new().append(1).append(2).append(3);
let mut iter = list.iter();
assert_eq!(iter.next(), Some(&3));
assert_eq!(iter.next(), Some(&2));
assert_eq!(iter.next(), Some(&1));
}
}

Loading…
Cancel
Save