diff --git a/codes/rust_lang/part03/Cargo.toml b/codes/rust_lang/part03/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..005d5bb3302af663c1014626a93d7e9a51cfa26a --- /dev/null +++ b/codes/rust_lang/part03/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "part03" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/codes/rust_lang/part03/src/main.rs b/codes/rust_lang/part03/src/main.rs new file mode 100644 index 0000000000000000000000000000000000000000..7cadbdc27915aa2495b46109fc526c770519620e --- /dev/null +++ b/codes/rust_lang/part03/src/main.rs @@ -0,0 +1,103 @@ +/// In part03 we introduce genericity through traits and in particular, [Copy], +/// [Clone], [std::fmt::Display] . + +enum SomethingOrNothing<T> { + Nothing, + Something(T), +} + +// We know the generic type T must be Displayable +impl<T: std::fmt::Display> SomethingOrNothing<T> { + // Static function + fn print(self) { + match self { + SomethingOrNothing::Nothing => println!("Nothing."), + SomethingOrNothing::Something(val) => println!("Something is: {}", val), + } + } +} + +impl<T: Clone> Clone for SomethingOrNothing<T> { + fn clone(&self) -> Self { + match self { + SomethingOrNothing::Nothing => SomethingOrNothing::Nothing, + SomethingOrNothing::Something(val) => SomethingOrNothing::Something(val.clone()), + } + } +} + +impl<T: Copy> Copy for SomethingOrNothing<T> {} + +// If we remove Copy, we have a problem with the t in tab +// in the computation of the minimum. +trait Minimum: Copy { + fn min(self, rhs: Self) -> Self; +} + +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::Something(lhs.min(rhs)) + } + (SomethingOrNothing::Nothing, SomethingOrNothing::Something(rhs)) => { + SomethingOrNothing::Something(rhs) + } + (SomethingOrNothing::Something(lhs), SomethingOrNothing::Nothing) => { + SomethingOrNothing::Something(lhs) + } + } + } +} + +// i32 is Copyable as a very basic type as f32, f64, etc. +// Arrays for example are not copyable. +impl Minimum for i32 { + fn min(self, rhs: Self) -> Self { + if self < rhs { + self + } else { + rhs + } + } +} + +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. +fn print_tab(tab: [i32; SIZE]) -> [i32; SIZE] { + for t in tab { + print!("{} ", t); + } + println!(); + tab +} + +fn find_min<T: Minimum>(tab: [T; SIZE]) -> ([T; SIZE], SomethingOrNothing<T>) { + let mut min = SomethingOrNothing::Nothing; + // Here is T is not Copyable tab is consumed and cannot be returned + for t in tab { + min = min.min(SomethingOrNothing::Something(t)); + } + (tab, min) +} + +fn main() { + let tab = read_command_line(); + + println!("Among the Somethings in the list:"); + let tab = print_tab(tab); + + // There are alternatives to access fields of tuples + let (_, min) = find_min(tab); + // The first field is not used therefore we can replace it with "_" + min.print(); +}