control flows

This commit is contained in:
2024-08-26 16:55:46 +02:00
parent d2a91425dc
commit 7e0c21cc42
4 changed files with 327 additions and 2 deletions

199
src/controlflow.rs Normal file
View File

@@ -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"),
_ => (),
}
}

85
src/conversion.rs Normal file
View File

@@ -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<i32> 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<Number> 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<i32> for EvenNumber {
type Error = ();
fn try_from(value: i32) -> Result<Self, Self::Error> {
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<EvenNumber, ()> = 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::<i32>().unwrap();
let sum = parsed + turbo_parsed;
println!("Sum: {:?}", sum);
}

View File

@@ -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();
}

35
src/traits.rs Normal file
View File

@@ -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<i32>,
}
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);
}