Explorar el Código

Third chapter done

master
Lachlan Jacob hace 5 años
padre
commit
059d2d1d42
Se han modificado 3 ficheros con 108 adiciones y 1 borrados
  1. 5
    0
      NOTES.md
  2. 2
    1
      lists/src/lib.rs
  3. 101
    0
      lists/src/third.rs

+ 5
- 0
NOTES.md Ver fichero

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 Ver fichero

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

+ 101
- 0
lists/src/third.rs Ver fichero

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

Cargando…
Cancelar
Guardar