↑Programmieren in Rust
mod list {
use std::fmt;
pub struct Node<T> {
pub item: T,
pub next: List<T>
}
pub enum List<T> {
None,
Node(Box<Node<T>>)
}
impl<T> List<T> {
pub fn node(item: T, next: List<T>) -> List<T> {
List::Node(Box::new(Node {item, next}))
}
pub fn map<U>(&self, f: impl Fn(T)->U) -> List<U>
where T: Clone
{
match self {
List::Node(node) => List::node(
f(node.item.clone()), node.next.map(f)),
List::None => List::None
}
}
}
pub fn list<T: Clone>(a: &[T]) -> List<T> {
a.iter().rev().fold(List::None,
|acc, x| List::node(x.clone(), acc))
}
impl<T: fmt::Display> fmt::Display for List<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "[")?;
let mut p = self;
let mut first = true;
while let List::Node(node) = p {
if first {first = false;} else {write!(f, ", ")?;}
write!(f, "{}", node.item)?;
p = &node.next;
}
write!(f, "]")
}
}
}
use list::{List, list};
fn main() {
let a: List<i32> = list(&[1, 2, 3, 4]);
println!("{}", a.map(|x| 2*x));
}
Probleme, die hier bewusst offen gelassen wurden:
T: Clone verschwinden.
map besser iterativ formulieren,
damit es nicht zu einem Überlauf des Aufrufstapels kommt.
drop
behebt dieses Problem.