control flows
This commit is contained in:
199
src/controlflow.rs
Normal file
199
src/controlflow.rs
Normal 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
85
src/conversion.rs
Normal 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);
|
||||
}
|
||||
10
src/main.rs
10
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();
|
||||
}
|
||||
|
||||
35
src/traits.rs
Normal file
35
src/traits.rs
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user