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 primitives;
|
||||||
//mod customtypes;
|
//mod customtypes;
|
||||||
//mod variablebindings;
|
//mod variablebindings;
|
||||||
mod types;
|
// mod types;
|
||||||
|
//mod conversion;
|
||||||
|
mod controlflow;
|
||||||
|
// mod traits;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
//helloworld::hello_world_module();
|
//helloworld::hello_world_module();
|
||||||
//primitives::primitives_module();
|
//primitives::primitives_module();
|
||||||
//customtypes::custom_types_module();
|
//customtypes::custom_types_module();
|
||||||
//variablebindings::variable_bindings_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