diff --git a/src/controlflow.rs b/src/controlflow.rs new file mode 100644 index 0000000..9e18fdd --- /dev/null +++ b/src/controlflow.rs @@ -0,0 +1,199 @@ +pub fn control_flow_module() { + let mut count = 0i32; + const BREAKPOINT: i32 = 20; + + let result = loop { + // infinite loop until break + // returning: loops return data put after the break + println!("{count}"); + + count += 1; + + if count >= BREAKPOINT { + break count; + } + }; + + // Nesting and labels + 'outer: loop { + 'inner: loop { + break 'outer; + } + } + + // FizzbBuzz on a while + // FizzBuzz if divisible by 3 and 5 + // Fizz if by 3 + // Buzz if by 5 + // i if none true + const LIMIT: i32 = 100; + let mut i: i32 = 1; + + println!("FizzBuzz: ["); + while i <= LIMIT { + if i % 15 == 0 { + print!("FizzBuzz"); + } else if i % 3 == 0 { + print!("Fizz"); + } else if i % 5 == 0 { + print!("Buzz"); + } else { + print!("{}", i); + } + + i += 1; + } + println!("]"); + + // FizzBuzz on a for + println!("FizzBuzz: ["); + for i in 1..=LIMIT { + if i % 15 == 0 { + print!("FizzBuzz"); + } else if i % 3 == 0 { + print!("Fizz"); + } else if i % 5 == 0 { + print!("Buzz"); + } else { + print!("{}", i); + } + } + println!("]"); + + // The for loop can interact with an Iterator + let numbers = vec!["One", "Two", "Three"]; + + for number in numbers.iter() { + // normal iterator + println!("{number}"); + } + + println!("{:?}", numbers); + + // into_iter : consumes the data and cant be reused + for number in numbers.into_iter() { + println!("{number}"); + } + //println!("{:?}", numbers); // CANT USE NUMBERS ANYMORE + + // ite_mut allows for mutation + let mut names = vec!["Name", "Another", "Not a name"]; + for name in names.iter_mut() { + *name = match name { + &mut "Not a name" => "He did not have a name!", + _ => "The did.", + } + } + + println!("{:?}", names); + + // match as a C switch all possible values must be covered + + let a_number = 20; + + match a_number { + 1 => println!("One"), + 2 | 3 | 5 | 7 | 11 => println!("Prime!"), + d if d > 18 => println!("Old!"), + _ => println!("Nothing to see here"), + } + + // match to destructure + // destructure tuples + let a_tuple = (1, 2, 3); + match a_tuple { + (0, y, z) => println!("something {y} {z}"), + (1, .., 3) => println!("First is three and last three, the rest does not matter"), + (1, ..) => println!("First is one, the rest does not matter"), + (2, .., 3) => println!("First is two and last three, the rest does not matter"), + _ => println!("This means to dont bind the value to a variable"), + } + + // desctructure arrays + let an_array = [1, 2, 3]; + match an_array { + [3, second, tail @ ..] => println!("{second} {:?}", tail), // this WONT + // trigger since + // does not match + [1, two, three] => println!("one {two} {three}"), + [fist, middle @ .., last] => println!("{fist}, {:?}, {last}", middle), + } + + // destructure enums + enum Colors { + Red, + Blue, + Green, + RGB(i32, i32, i32), + } + + let my_red: Colors = Colors::RGB(20, 10, 10); + + match my_red { + Colors::Red => println!("It's red!"), + Colors::Blue => println!("It's blue!"), + Colors::Green => println!("It's green!"), + Colors::RGB(r, g, b) => println!("It's {r}{g}{b}"), + } + + // destructuring pointers/ref + // you need to iether use &, ref, ref mut or dereference before the match with * + let reference = &1; + + match reference { + &val => println!("The value of the reference {:?}", val), + } + + match *reference { + val => println!("The value of the reference {:?}", val), + } + + // also can retrieve references via ref and ref mut + let value = 10; + let mut mut_value = 1010; + + match value { + ref r => println!("Reference to a value: {:?}", r), + } + + match mut_value { + ref mut m => { + *m += 10; + println!("An increment of ten turns out to be: {:?}", m); + } + } + + // structs can also be destructured + struct Foo { + x: (u32, u32), + y: u32, + } + + let foo = Foo { x: (1, 2), y: 3 }; + + match foo { + Foo { x: (1, b), y } => println!("First of x is 1, b = {}, y = {} ", b, y), + + Foo { y: 2, x: i } => println!("y is 2, i = {:?}", i), + + Foo { y, .. } => println!("y = {}, we don't care about x", y), + } + + // Guards can be added to filter an arm, but they wont count when the compiler checks if all + // the possible values are covered + let number = 4; + match number { + i if i == 0 => println!("Zero"), + i if i > 0 => println!("Gt than zero"), + i if i < 0 => println!("Lt than zero"), + _ => println!("Another"), // required since the guard is not taken into account for arm + // checking + } + + // With match you can bind a value to a name + let another_number = 4; + match another_number { + n @ 1..5 => println!("{n} is between 1 and 5"), + _ => (), + } +} diff --git a/src/conversion.rs b/src/conversion.rs new file mode 100644 index 0000000..85c2fbb --- /dev/null +++ b/src/conversion.rs @@ -0,0 +1,85 @@ +pub fn conversion_module() { + // From and Into traits + use std::convert::From; + + #[derive(Debug)] + struct Number { + value: i32, + } + + // From is how to create itself from another type + impl From for Number { + fn from(item: i32) -> Self { + Number { value: item + 1337 } + } + } + let num = Number::from(30); + println!("My number is {:?}", num); + + // Into is how to convert a type _into_ another + // use std::convert::Into; + // impl Into for i32 { + // fn into(self) -> Number { + // Number { value: self } + // } + // } + // + // Into will call From when necesary, so there is no need to implement. This does not work the + // other way arround + let int = 5; + let num: Number = int.into(); + println!("My number is {:?}", num); + + // TryFrom and TryInto + // These are used on fallible conversions and, tehrefore, return a `Result` + + use std::convert::TryFrom; + use std::convert::TryInto; + + #[derive(Debug, PartialEq)] + struct EvenNumber(i32); + + impl TryFrom for EvenNumber { + type Error = (); + + fn try_from(value: i32) -> Result { + if value % 2 == 0 { + Ok(EvenNumber(value)) + } else { + Err(()) + } + } + } + + assert_eq!(EvenNumber::try_from(8), Ok(EvenNumber(8))); // we can make assertions + assert_eq!(EvenNumber::try_from(1), Err(())); // we can make assertions + + let result: Result = 5i32.try_into(); + assert_eq!(result, Err(())); + + // To and from Strings + // One way is to implement a ToString trait, but is preferable to implement fmt::Display, that + // provides automatically ToString. + + use std::fmt; + + struct Person { + height: i32, + } + + impl fmt::Display for Person { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "This person is {}cm tall", self.height) + } + } + + let my_person = Person { height: 150 }; + println!("{}", my_person.to_string()); + + // From string + let parsed: i32 = "5".parse().unwrap(); + let turbo_parsed = "10".parse::().unwrap(); + + let sum = parsed + turbo_parsed; + println!("Sum: {:?}", sum); +} diff --git a/src/main.rs b/src/main.rs index 98dd0c0..78be55e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,12 +9,18 @@ //mod primitives; //mod customtypes; //mod variablebindings; -mod types; +// mod types; +//mod conversion; +mod controlflow; +// mod traits; fn main() { //helloworld::hello_world_module(); //primitives::primitives_module(); //customtypes::custom_types_module(); //variablebindings::variable_bindings_module(); - types::types_module(); + //types::types_module(); + //conversion::conversion_module(); + controlflow::control_flow_module(); + //traits::traits_exercise(); } diff --git a/src/traits.rs b/src/traits.rs new file mode 100644 index 0000000..9b31633 --- /dev/null +++ b/src/traits.rs @@ -0,0 +1,35 @@ +/* + * Objectives + * 1. Define a trait + * 2. Create a type + * 3. Define an implementation of the trait for that type + * 4. Extend the trait with a second function and see what happens + * */ + +pub trait Move { + fn to(&mut self, x: i32, y: i32); +} + +struct Human { + name: String, + position: Vec, +} + +impl Move for Human { + fn to(&mut self, x: i32, y: i32) { + self.position = vec![x, y]; + } +} + +pub fn traits_exercise() { + let mut me = Human { + name: "Dani".to_string(), + position: vec![0, 0], + }; + + println!("My name is {} and i'm at {:?}", me.name, me.position); + + me.to(10, 20); + + println!("My name is {} and i'm at {:?}", me.name, me.position); +}