Standard traits

Implementing standard traits for your own types make them work more nicely (and more idiomatically) with the rest of the Rust ecosystem. So let's make the data types you have defined well-behaved ecosystem citizens!

Exercise 2.a: Implement the Display trait for your Stack (and possibly also for List, if it helps), so that stacks can be pretty-printed like this:

#![allow(unused)]
fn main() {
let mut s = Stack::new();
s.push(10);
s.push(20);
s.push(30);
println!("stack content: {s}");
}
stack content: [ 30 20 10 ]

Exercise 2.b: You lists and stacks, after all, are just glorified integer vectors. It makes sense to ease conversions between them and Vec<i32> and we have seen how the From trait is the idiomatic Rust way for supporting type conversions. Implement conversions in both directions, from Vec<i32> to List and from List to Vec<i32>. Once you have done this, you can do the same for Stack, by simply calling into the conversions you have already implemented for List (with some little extra work to precompute the stack length).

At the end, something like the following should work for your types:

#![allow(unused)]
fn main() {
// Vec<i32> -> List
let v = vec![1, 2, 3];
assert_eq!(
    List::from(v),
    Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))))
);

// List -> Vec<i32>
let l = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
assert_eq!(
    vec![1, 2, 3],
    Vec::<i32>::from(l)
);
}

Note that this is the first time we implement a trait for a type in a different crate than our own, specifically we are implementing From<List> for Vec<i32>, which is a generic type defined in the standard library. Doing so is permitted by Rust provided that you respect the orphan rule, i.e.: either the trait or the type for which you are implementing the trait must be defined in the same crate as the implementation.

Exercise 2.c: Implement the FromStr trait for your Stack (and possibly List), so that stacks can be parsed from string like this:

#![allow(unused)]
fn main() {
let mut s1 = Stack::new();
s1.push(10);
s1.push(20);
s1.push(30);

let s2: Stack = "[ 30 20 10 ]".parse().unwrap();

assert_eq!(s1, s2);
}