use std::rc::Rc;
use std::ops::Deref;
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum List<T> {
Cons(T, Rc<List<T>>),
Nil
}
impl<T: Clone> Clone for List<T> {
fn clone(&self) -> Self {
match self {
&List::Cons(ref head, ref tail) => {
List::Cons(head.clone(), tail.clone())
},
&List::Nil => List::Nil
}
}
}
impl<T> List<T> {
#[inline]
pub fn is_empty(&self) -> bool {
match &self {
&List::Cons(_, _) => false,
&List::Nil => true
}
}
#[inline]
pub fn iter(&self) -> ListIterator<T> where T: Clone {
ListIterator { list: self.clone() }
}
#[inline]
pub fn as_list(&self) -> Self where T: Clone {
self.clone()
}
#[inline]
pub fn singleton(item: T) -> Self {
List::Cons(item, Rc::new(List::Nil))
}
pub fn remove(&self, item: T) -> Option<(T, Self)> where T: Clone + Eq {
let mut first = List::Nil;
let mut curr = self;
loop {
match curr {
&List::Nil => {
return None;
},
&List::Cons(ref head, ref tail) if item == *head => {
let update = first.append_rev(tail.clone());
return Some((head.clone(), update));
},
&List::Cons(ref head, ref tail) => {
first = List::Cons(head.clone(), Rc::new(first));
curr = tail.deref();
}
}
}
}
pub fn remove_by<F>(&self, predicate: F) -> Option<(T, Self)>
where T: Clone,
F: Fn(&T) -> bool
{
let mut first = List::Nil;
let mut curr = self;
loop {
match curr {
&List::Nil => {
return None;
},
&List::Cons(ref head, ref tail) if predicate(head) => {
let update = first.append_rev(tail.clone());
return Some((head.clone(), update));
},
&List::Cons(ref head, ref tail) => {
first = List::Cons(head.clone(), Rc::new(first));
curr = tail.deref();
}
}
}
}
pub fn exists<F>(&self, predicate: F) -> bool
where T: Clone,
F: Fn(&T) -> bool
{
let mut curr = self;
loop {
match curr {
&List::Nil => {
return false;
},
&List::Cons(ref head, _) if predicate(head) => {
return true;
},
&List::Cons(_, ref tail) => {
curr = tail.deref();
}
}
}
}
pub fn find<F>(&self, predicate: F) -> Option<T>
where T: Clone,
F: Fn(&T) -> bool
{
let mut curr = self;
loop {
match curr {
&List::Nil => {
return None;
},
&List::Cons(ref head, _) if predicate(head) => {
return Some(head.clone());
},
&List::Cons(_, ref tail) => {
curr = tail.deref();
}
}
}
}
#[inline]
pub fn reversed(&self) -> Self where T: Clone {
self.append_rev(Rc::new(List::Nil))
}
#[inline]
pub fn append(&self, other: Rc<Self>) -> Self where T: Clone {
self.reversed().append_rev(other)
}
fn append_rev(&self, tail: Rc<Self>) -> Self where T: Clone {
let mut result = tail;
let mut curr = self;
loop {
match curr {
&List::Nil => {
return (*result).clone();
},
&List::Cons(ref head, ref tail) => {
curr = tail.deref();
let list = List::Cons(head.clone(), result);
match curr {
&List::Nil => {
return list;
},
&List::Cons(_, _) => {
result = Rc::new(list);
}
}
}
}
}
}
}
impl<T: Clone> IntoIterator for List<T> {
type Item = T;
type IntoIter = ListIterator<T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
ListIterator { list: self.clone() }
}
}
pub struct ListIterator<T> {
list: List<T>
}
impl<T: Clone> Iterator for ListIterator<T> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let (item, tail) = {
match &self.list {
&List::Cons(ref head, ref tail) => {
let item = head.clone();
let tail = tail.as_list();
(Some(item), tail)
},
&List::Nil => {
(None, List::Nil)
}
}
};
self.list = tail;
item
}
}