/* ANCHOR: all */
/// In gen_types_composes we introduce genericity through traits and in particular, [Copy],
/// [Clone], [std::fmt::Display] .
// ANCHOR: something_or_nothing
enum SomethingOrNothing<T> {
Nothing,
Something(T),
}
// ANCHOR_END: something_or_nothing
// ANCHOR: new
impl<T> SomethingOrNothing<T> {
fn new(val: T) -> SomethingOrNothing<T> {
SomethingOrNothing::Something(val)
}
}
// ANCHOR_END: new
// ANCHOR: print
// Print function
// We know the generic type T must be Displayable
fn print<T: std::fmt::Display>(val: SomethingOrNothing<T>) {
match val {
SomethingOrNothing::Nothing => println!("Nothing."),
SomethingOrNothing::Something(val) => println!("Something is: {}", val),
}
}
// ANCHOR_END: print
// ANCHOR: clone
impl<T: Clone> Clone for SomethingOrNothing<T> {
fn clone(&self) -> Self {
match self {
SomethingOrNothing::Nothing => SomethingOrNothing::Nothing,
SomethingOrNothing::Something(val) => SomethingOrNothing::new(val.clone()),
}
}
}
// ANCHOR_END: clone
// ANCHOR: copy
impl<T: Copy> Copy for SomethingOrNothing<T> {}
// ANCHOR_END: copy
// If we remove Copy, we have a problem with the t in tab
// in the computation of the minimum.
// ANCHOR: minimum
trait Minimum: Copy {
fn min(self, rhs: Self) -> Self;
}
// ANCHOR_END: minimum
// ANCHOR: minimum_impl
impl<T: Minimum> Minimum for SomethingOrNothing<T> {
fn min(self, rhs: Self) -> Self {
match (self, rhs) {
(SomethingOrNothing::Nothing, SomethingOrNothing::Nothing) => {
SomethingOrNothing::Nothing
}
(SomethingOrNothing::Something(lhs), SomethingOrNothing::Something(rhs)) => {
SomethingOrNothing::new(lhs.min(rhs))
}
(SomethingOrNothing::Nothing, SomethingOrNothing::Something(rhs)) => {
SomethingOrNothing::new(rhs)
}
(SomethingOrNothing::Something(lhs), SomethingOrNothing::Nothing) => {
SomethingOrNothing::new(lhs)
}
}
}
}
// ANCHOR_END: minimum_impl
// i32 is Copy, like other primitive types (f32, f64, etc.).
// Fixed-size arrays [T; N] are also Copy when T is Copy.
// ANCHOR: minimum_i32
impl Minimum for i32 {
fn min(self, rhs: Self) -> Self {
if self < rhs { self } else { rhs }
}
}
// ANCHOR_END: minimum_i32
const SIZE: usize = 9;
fn read_command_line() -> [i32; SIZE] {
[10, 32, 12, 43, 52, 53, 83, 2, 9]
}
// Prints tab and returns tab.
// Tab would be destructed at the end of the function otherwise.
// ANCHOR: print_tab
fn print_tab<T: std::fmt::Display>(tab: [T; SIZE]) {
for t in tab {
print!("{} ", t);
}
println!();
}
// ANCHOR_END: print_tab
// ANCHOR: find_min
fn find_min<T: Minimum>(tab: [T; SIZE]) -> SomethingOrNothing<T> {
let mut current_minimum = SomethingOrNothing::Nothing;
// Here, if T is not Copyable, tab is consumed and cannot be returned
for t in tab {
current_minimum = current_minimum.min(SomethingOrNothing::new(t));
}
current_minimum
}
// ANCHOR_END: find_min
// ANCHOR: main
fn main() {
let tab = read_command_line();
println!("Among the Somethings in the list:");
print_tab(tab);
let min = find_min(tab);
print(min);
}
// ANCHOR_END: main
/* ANCHOR_END: all */