Przeglądaj źródła

Third chapter done

master
Lachlan Jacob 5 lat temu
rodzic
commit
059d2d1d42
3 zmienionych plików z 108 dodań i 1 usunięć
  1. 5
    0
      NOTES.md
  2. 2
    1
      lists/src/lib.rs
  3. 101
    0
      lists/src/third.rs

+ 5
- 0
NOTES.md Wyświetl plik

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 Wyświetl plik

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

+ 101
- 0
lists/src/third.rs Wyświetl plik

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));
}
}

Ładowanie…
Anuluj
Zapisz