枚举实现的列表,支持构建加头,原地加头,取头引用,取头所有权,取尾引用,过滤,反转,左右折叠,过滤,Map/Reduce
#![allow(warnings)]
#![allow(unused)]
use std::fmt;
use std::mem;
use std::boxed::Box;
enum List<T> {
Nil,
Cons(T, Box<List<T>>),
}
impl <T> List<T> {
//消费型添加,将头加到原列表上,创建新owner,原owner被owner的内部拥有,支持链式调用和从临时变量开始调用
fn cons(self, item: T) -> Self {
List::Cons(item, Box::new(self))
}
//可变引用型添加:原owner 先被 List::Nil 将原值置换出来,然后将原值加上新头后被重新设置回去,也支持链式调用,但不支持从临时变量开始调用
pub fn add(&mut self, value: T) -> &mut Self {
let old = mem::replace(self, List::Nil);
*self = List::Cons(value, Box::new(old));
self
}
fn tail(&self) -> &Self {
match self {
List::Nil => self,
List::Cons(_, t) => &**t,
}
}
fn take_head(&mut self) -> Option<T> {
//一步一步的将 self 用 List::Nil 将原值置换出来
match mem::replace(self, List::Nil) {
List::Nil => None,
List::Cons(h, t) => {
*self = *t; //用已置为List::Nil 的 self 设置为原值的尾
Some(h)
}
}
}
fn head(&self) -> Option<&T> {
match self {
List::Nil => None,
List::Cons(h,_) => Some(h),
}
}
fn fold_right<U>(self, init: U, f: &impl Fn(T, U) -> U) -> U
{
match self {
List::Nil => init,
List::Cons(v, next) => f(v, next.fold_right(init, f)),
}
}
fn fold_left<U>(self, init: U, f: &impl Fn(U, T) -> U) -> U
{
match self {
List::Nil => init,
List::Cons(v, next) => next.fold_left(f(init, v), f),
}
}
fn reverse(self) -> Self {
return self.fold_left(List::Nil, &|acc, x| acc.cons(x));
}
fn filter(self, f: &impl Fn(&T) -> bool ) -> Self
{
return self.fold_left(List::Nil, &|x, y| {if f(&y) {x.cons(y)} else {x}});
}
fn reduce<U>(self,i:U,f:&impl Fn(U,T)->U) -> U {
match self {
List::Nil => i,
List::Cons(h, t) => t.reduce(f(i,h), f),
}
}
fn into_vec(self) -> Vec<T> {
return self.reduce(Vec::<T>::new(), &|mut x,y|{x.push(y);x})
}
fn iter(&self) -> ListIter<'_, T> {
ListIter { current: self }
}
}
impl<T: fmt::Debug> fmt::Debug for List<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
List::Nil => write!(f, "nil" ),
List::Cons(head, tail) => write!(f,"{:?} -> {:?}" , head, tail),
}
}
}
//1、迭代器结构体 被实现消费型迭代器的数据结构名+IntoIter
struct ListIntoIter<T> {
current : List<T> //持有原数据的所有权,用来保存"当前遍历到了哪里"的状态
}
//2、实现 Iterator trait 核心是实现 next() 方法
impl<T> Iterator for ListIntoIter<T> {
type Item = T; // 产出的元素类型
fn next(&mut self) -> Option<Self::Item> {
self.current.take_head()
}
}
//3、实现 IntoIterator trait ,将你的数据结构与迭代器关联起来
impl <T> IntoIterator for List<T> {
type Item = T;
type IntoIter = ListIntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
ListIntoIter { current: self }
}
}
struct ListIter<'a,T> {
current: &'a List<T>
}
impl<'a, T> Iterator for ListIter<'a, T>{
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
match self.current {
List::Nil => None,
List::Cons(h, t) => {
self.current = t;
Some(h)
}
}
}
}
impl<'a, T> IntoIterator for &'a List<T> {
type Item = &'a T;
type IntoIter = ListIter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
ListIter { current: self }
}
}
fn main() {
let mut t = List::Nil.cons(1).cons(2).cons(3);
t.add(4).add(5).add(6); //t 未被消费,不能赋给一个变量,否则t 被 move ,而且必须从非 临时字面量 上调用
let u = t.cons(7).cons(8); // t 被消费掉无法引用,必须赋给一个新变量来使用
for item in u.iter() {//借用迭代器 或使用 for item in &u , 消费型迭代器 for item in u
print!("{} ",item);
}
println!("\n{:?}",u);
}