Last active
August 14, 2020 18:01
-
-
Save miguelcnf/ce44b7fe4655194bf6bde5081c759cdd to your computer and use it in GitHub Desktop.
Raw notes taken during the udemy The Rust Programming Language course by Dmitri Nesteruk
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![allow(dead_code)] | |
use std::collections::{HashMap, HashSet}; | |
use std::mem; | |
fn main() { | |
println!("Hello, world!"); | |
// test_vars(); | |
// test_operators(); | |
// test_constants(); | |
// let stack = test_stack(); | |
// println!("stack = {}", stack); | |
// println!("stack = {:p}", &stack); | |
// let boxed = test_heap(); | |
// println!("boxed = {}", boxed); | |
// println!("boxed = {:p}", boxed); | |
// test_if_statement(); | |
// test_looping(); | |
// test_match(); | |
// test_struct(); | |
// test_enums(); | |
// test_unions(); | |
// test_option_of_t(); | |
// test_arrays(); | |
// test_slices(); | |
// test_tuples(); | |
// test_pattern_matching(); | |
// test_generics(); | |
// test_vectors(); | |
// test_hashmaps(); | |
// test_hashset(); | |
// test_strings(); | |
// test_functions(); | |
// test_methods(); | |
// test_closures(); | |
// test_traits(); | |
// test_ownership(); | |
// test_borrowing(); | |
} | |
fn test_borrowing() { | |
let a = vec![1, 2, 3]; | |
let _b = &a; | |
println!("{:?}", a); // compiles because it borrows a instead of moving ownership above (gets a reference) | |
let mut x = 1; | |
let y = &mut x; | |
*y += 1; | |
println!("x = {}", x); | |
} | |
fn test_ownership() { | |
// let a = vec![1, 2, 3]; | |
// let _b = a; | |
// println!("{:?}", a); // compile time error: trying to borrow after move because vec is a pointer to heap allocated values | |
let u = 1; | |
let _uu = u; | |
println!("{}", u); // compiles because it copies stack-allocated values (i32) | |
// let v = Box::new(1); | |
// let _vv = v; | |
// println!("{}", v) // compile time error: (same as above) | |
} | |
fn test_traits() { | |
trait Animal { | |
fn new(name: &'static str) -> Self; | |
fn name(&self) -> &'static str; | |
fn talk(&self) { | |
println!("{} cannot talk", self.name()) | |
} | |
} | |
struct Human { | |
name: &'static str | |
} | |
impl Animal for Human { | |
fn new(name: &'static str) -> Self { | |
return Human { name }; | |
} | |
fn name(&self) -> &'static str { | |
return self.name; | |
} | |
fn talk(&self) { | |
println!("{} says hi!", self.name) | |
} | |
} | |
struct Cat { | |
name: &'static str | |
} | |
impl Animal for Cat { | |
fn new(name: &'static str) -> Self { | |
return Cat { name }; | |
} | |
fn name(&self) -> &'static str { | |
return self.name; | |
} | |
fn talk(&self) { | |
println!("{} says meow!", self.name) | |
} | |
} | |
let human = Human { name: "Miguel" }; | |
human.talk(); | |
let cat = Cat::new("Loa"); | |
cat.talk(); | |
let cat2: Cat = Animal::new("Braiken"); | |
cat2.talk(); | |
trait Summable<T> { | |
fn sum(&self) -> T; | |
} | |
impl Summable<i32> for Vec<i32> { | |
fn sum(&self) -> i32 { | |
let mut sum = 0; | |
for x in self { | |
sum += *x; | |
} | |
return sum; | |
} | |
} | |
let vector = Vec::from([1, 2, 3, 4]); | |
println!("sum of vector = {}", vector.sum()); | |
fn function_with_trait_arg<T>(summable: impl Summable<T>) -> T { | |
return summable.sum(); | |
} | |
println!("sum of vector from func = {}", function_with_trait_arg(vector)) | |
// fn func(arg: impl Trait1 + Trait2) ... | |
// fn func<T: Debug>(debuggable: T) {} | |
// fn func<T>(debuggable: T) where T: Debug {} | |
} | |
fn test_closures() { | |
fn say_hello() { | |
println!("hello"); | |
} | |
let sh = say_hello; | |
sh(); | |
let inc = |x: i32| -> i32 { x + 1 }; | |
println!("{}", inc(1)); | |
let inc_v2 = |x| { x + 1 }; | |
println!("{}", inc_v2(1)); | |
let two = 2; | |
let double = |x| { x * two }; | |
println!("{}", double(10)); | |
// let borrow_two = &mut two; // cannot borrow two because of the closure | |
let mut three = 3; | |
{ | |
let triple = |x| { x * three }; | |
println!("{}", triple(10)); | |
} | |
let borrow_three = &mut three; // compiles because we guarantee that the borrow inside the closure is destroyed with the scope | |
println!("{}", borrow_three); | |
let power_of_2 = |x: &mut i32| { | |
*x *= *x; | |
}; | |
let mut x = 4; | |
power_of_2(&mut x); | |
println!("{}", x) | |
} | |
fn test_methods() { | |
struct Point { | |
x: i32, | |
y: i32, | |
} | |
impl Point { | |
fn get_x(&self) -> i32 { | |
self.x | |
} | |
} | |
let point = Point { x: 100, y: 200 }; | |
println!("point x is {}", point.get_x()) | |
} | |
fn test_functions() { | |
fn rcv(x: i32) { | |
println!("{}", x) | |
} | |
rcv(100); | |
fn increment(x: &mut i32) { | |
*x += 1; | |
} | |
let mut i = 100; | |
increment(&mut i); | |
println!("{}", i); | |
fn product(x: i32, y: i32) -> i32 { | |
x * y // implicit last statement return | |
} | |
println!("{}", product(10, 34)) | |
} | |
fn test_strings() { | |
let s = "string"; // let s:&'static str = "string" -> string slice statically allocated | |
for c in s.chars() { | |
println!("{}", c); | |
} | |
if let Some(x) = s.chars().nth(0) { | |
println!("first char is {}", x); | |
} | |
let mut string = String::new(); | |
string.push_str("str"); | |
string.push('i'); | |
string.push_str("ng"); | |
println!("{}", string); | |
let z = s.to_owned() + " concat"; // String (to_owned) + str | |
let zz = string + " concat"; // String + str | |
println!("{}", z); | |
println!("{}", zz); | |
let x = String::from("from"); | |
let y = "from".to_string(); | |
println!("{}", x); | |
println!("{}", y); | |
println!("{}", x.replace("from", "to")); | |
let name = "ez"; | |
let hi = format!("hi {}!", name); | |
println!("{}", hi); | |
let run = "run"; | |
let forest = "forest"; | |
println!("{0} {1} {0}", run, forest); | |
println!("{run} {forest} {run}", run = run, forest = forest); | |
} | |
fn test_hashset() { | |
let mut set: HashSet<i32> = HashSet::new(); | |
set.insert(1); | |
set.insert(2); | |
set.insert(2); | |
println!("{:?}", set); | |
let added = set.insert(2); | |
println!("added = {}", added); | |
if set.contains(&1) { | |
println!("contains 1") | |
} | |
let _1_5: HashSet<_> = (1..=5).collect(); | |
let _1_10: HashSet<_> = (1..=10).collect(); | |
if _1_5.is_subset(&_1_10) { | |
println!("{:?} is a subset of {:?}", _1_5, _1_10); | |
} | |
// is_disjoint | |
// union | |
// intersection | |
// etc. | |
} | |
fn test_hashmaps() { | |
let mut map = HashMap::new(); | |
map.insert("1", 1); | |
map.insert("2", 2); | |
println!("k = 1, v = {}", map["1"]); | |
for (k, v) in &map { | |
println!("k = {}, v = {}", k, v) | |
} | |
map.insert("100", 100); | |
map.remove("100"); | |
if !map.contains_key("100") { | |
println!("not contains 100"); | |
} | |
let value = map.entry("100").or_insert(100); | |
println!("{}", value); | |
map.insert("100", 101); | |
println!("k = 100, v = {}", map["100"]); | |
} | |
fn test_vectors() { | |
// grow-able array | |
let mut v = Vec::new(); | |
v.push(1); | |
v.push(2); | |
println!("v = {:?}", v); | |
println!("v[0] = {}", v[0]); | |
v[0] = 10; | |
println!("v[0] = {}", v[0]); | |
match v.get(1) { | |
None => println!("no such element"), | |
Some(val) => println!("v[100] = {}", val), | |
} | |
for x in &v { | |
// lifo | |
println!("{}", x) | |
} | |
v.push(100); | |
let last_elem = v.pop(); | |
// debug cause its an Option | |
println!("popped last element = {:?}", last_elem); | |
while let Some(x) = v.pop() { | |
println!("{}", x) | |
} | |
} | |
fn test_generics() { | |
struct Point<T> { | |
x: T, | |
y: T, | |
} | |
let point_int = Point { x: 1, y: 20 }; | |
let point_float = Point { x: 1.123, y: 20.20 }; | |
println!("point int x = {}, y = {}", point_int.x, point_int.y); | |
println!("point float x = {}, y = {}", point_float.x, point_float.y) | |
} | |
fn test_pattern_matching() { | |
for x in 0..13 { | |
let amount = match x { | |
0 => "no", | |
1 | 2 => "one or two", | |
z @ 3..=7 => if z % 2 == 0 { "some" } else { "a few" }, | |
12 => "a dozen", | |
_ => "a bunch of" | |
}; | |
println!("{}: we have {} oranges", x, amount) | |
} | |
let point = (0, 10); | |
match point { | |
(0, 0) => println!("origin"), | |
(0, _) => println!("x axis"), | |
(x, 0) => println!("y axis, x = {}", x), | |
(x, y) => println!("x = {}, y = {}", x, y) | |
} | |
} | |
fn test_tuples() { | |
let a = 2; | |
let b = 5; | |
let tuple = (a + b, a * b); | |
println!("tuple = {:?}", tuple); | |
println!("tuple 0 == {}", tuple.0); | |
println!("tuple 1 == {}", tuple.1); | |
let (a, b) = tuple; | |
println!("a == {}", a); | |
println!("b == {}", b); | |
} | |
fn test_slices() { | |
let array: [i32; 5] = [1, 2, 3, 4, 5]; | |
let partial_sliced_array = &array[1..4]; | |
println!("partial sliced array = {:?}", partial_sliced_array); | |
let sliced_array = &array; | |
println!("sliced array = {:?}", sliced_array); | |
let slice: &[i32] = &mut [1, 2, 3]; | |
println!("slice = {:?}", slice); | |
} | |
fn test_arrays() { | |
// array sizes are immutable | |
let mut a: [i32; 5] = [1, 2, 3, 4, 5]; | |
println!("a has {} elements", a.len()); | |
println!("a[0] = {}", a[0]); | |
a[0] = 100; | |
println!("a[0] = {}", a[0]); | |
println!("{:?}", a); | |
if a != [1, 2, 3, 4, 5] { | |
println!("not equals"); | |
} | |
if a.contains(&100) { | |
println!("contains"); | |
} | |
let b = [1; 10]; // elements are initialised as i32 with value 1 | |
for i in 0..b.len() { | |
println!("val = {}", b[i]) | |
} | |
println!("size of b = {} bits", mem::size_of_val(&b) * 8); | |
let c = [1i8; 10]; // elements are initialised as i8 with value 1 | |
for i in 0..c.len() { | |
println!("val = {}", c[i]) | |
} | |
println!("size of c = {} bits", mem::size_of_val(&c) * 8); | |
let matrix: [[f32; 3]; 2] = | |
[ | |
[1.0, 0.0, 0.0], | |
[2.0, 0.0, 0.0] | |
]; | |
println!("matrix = {:?}", matrix); | |
for i in 0..matrix.len() { | |
println!("matrix[{}][0] = {}", i, matrix[i][0]) | |
} | |
} | |
fn test_option_of_t() { | |
let a = 10; | |
let b = 2; | |
let result = if b != 0 { | |
Some(a / b) | |
} else { | |
None | |
}; | |
match result { | |
None => { println!("cannot divide by zero") } | |
Some(val) => { println!("{}/{} = {}", a, b, val) } | |
} | |
if let Some(val) = result { | |
println!("result = {}", val) | |
} | |
while let Some(val) = result { | |
println!("result = {}", val); | |
break; // break otherwise equivalent to while true | |
} | |
} | |
fn test_unions() { | |
union IntOrFloat { | |
i: i32, | |
f: f32, | |
} | |
let mut iof = IntOrFloat { i: 23 }; | |
let val = unsafe { iof.i }; | |
println!("val = {}", val); | |
iof = IntOrFloat { f: 100.100 }; | |
unsafe { | |
match iof { | |
IntOrFloat { i: 23 } => { | |
println!("42"); | |
} | |
IntOrFloat { f } => { | |
println!("any float = {}", f) | |
} | |
} | |
} | |
iof = IntOrFloat { i: 23 }; | |
unsafe { | |
match iof { | |
IntOrFloat { f } => { | |
println!("int as float = {}", f); | |
} | |
} | |
} | |
} | |
fn test_enums() { | |
enum Color { | |
Red, | |
Green, | |
Blue, | |
RgbColor(u8, u8, u8), | |
Cmyk { cyan: u8, magenta: u8, yellow: u8, black: u8 }, | |
} | |
let c: Color = Color::Cmyk { | |
cyan: 10, | |
magenta: 0, | |
yellow: 0, | |
black: 255, | |
}; | |
match c { | |
Color::Red => { println!("r") } | |
Color::Green => { println!("g") } | |
Color::Blue => { println!("b") } | |
Color::RgbColor(0, 0, 0) | |
| Color::Cmyk { cyan: _, magenta: _, yellow: _, black: 255 } => { println!("black") } | |
Color::RgbColor(r, g, b) => { println!("rgb({},{},{})", r, g, b) } | |
Color::Cmyk { cyan: c, magenta: m, yellow: y, black: b } => { println!("cmyk({},{},{},{})", c, m, y, b) } | |
} | |
} | |
fn test_struct() { | |
struct X { | |
x: String | |
} | |
let x = X { x: String::from("test") }; | |
println!("x = {}", x.x); | |
} | |
fn test_match() { | |
let country_code = 44; | |
let country = match country_code { | |
44 => "UK", | |
46 => "Sweden", | |
1..=1000 => "unknown", | |
_ => "invalid" | |
}; | |
println!("code = {}, country = {}", country_code, country) | |
} | |
fn test_looping() { | |
let mut x = 1; | |
while x < 1000 { | |
x *= 2; | |
if x == 64 { | |
continue; | |
} | |
println!("x = {}", x); | |
} | |
let mut y = 1; | |
loop { | |
y *= 2; | |
println!("y = {}", y); | |
if y == 1 << 10 { // 2^10 | |
break; | |
} | |
} | |
for x in 1..11 { | |
println!("x = {}", x); | |
} | |
for (i, v) in (30..41).enumerate() { | |
println!("i = {}, v = {}", i, v); | |
} | |
} | |
fn test_if_statement() { | |
let temp = 25; | |
if temp > 30 { | |
println!("hot"); | |
} else if temp < 10 { | |
println!("cold"); | |
} else { | |
println!("ok"); | |
} | |
let day = if temp > 20 { "sunny" } else { "cloudy" }; | |
println!("day = {}", day); | |
println!("it is {}", | |
if temp > 30 | |
{ "host" } else if temp < 10 | |
{ "cold" } else { "ok" } | |
); | |
println!("it is {}", | |
if temp > 20 { | |
if temp == 25 { "25" } else { "hot" } | |
} else { "cool" } | |
); | |
} | |
fn test_stack() -> i32 { | |
let x = 5; // x value is on the stack | |
println!("x = {}", x); | |
println!("x size = {} bytes", mem::size_of_val(&x)); | |
println!("x mem addr = {:p}", &x); | |
return x; | |
} | |
fn test_heap() -> Box<i32> { | |
let xx = Box::new(5); // boxing: xx value is a pointer to a heap addr | |
println!("xx = {}", xx); // dereference is done automatically, we could do *xx instead | |
println!("xx size = {} bytes", mem::size_of_val(&xx)); | |
println!("xx mem addr = {:p}", xx); | |
let mut yy = *xx; // unboxing | |
println!("yy = {}", yy); | |
yy = 10; | |
println!("yy = {}", yy); | |
return xx; | |
} | |
fn test_constants() { | |
const MEANING_OF_LIFE: u8 = 42; // no fixed addr | |
println!("meaning of life = {}", MEANING_OF_LIFE); | |
static TEST: u8 = 123; | |
println!("test = {}", TEST); | |
static mut UNSAFE: u8 = 123; | |
unsafe { | |
println!("unsafe = {}", UNSAFE); | |
} | |
} | |
fn test_operators() { | |
let mut a = 2 + 3 * 4; | |
println!("a = {}", a); | |
a = a + 1; | |
println!("a = {}", a); | |
a -= 2; | |
println!("a = {}", a); | |
println!("remainder of {} / {} = {}", a, 3, a % 3); | |
let pi_less_4 = std::f64::consts::PI < 4.0; | |
print!("pi is less than 4 = {}", pi_less_4); | |
} | |
fn test_vars() { | |
let a: u8 = 123; | |
println!("a = {}", a); | |
let mut b = 0; | |
println!("b = {}", b); | |
b = 123; | |
println!("b = {}", b); | |
let c = 123456789; | |
println!("c = {}, size = {} bytes", c, mem::size_of_val(&c)); | |
let d: isize = 123; | |
println!("d = {}, take up {} bytes, {}-bit os", d, mem::size_of_val(&d), mem::size_of_val(&d) * 8); | |
let e = 'x'; | |
println!("e = {}, size = {} bytes", e, mem::size_of_val(&e)); | |
let f = 2.5; | |
println!("f = {}, size = {} bytes", f, mem::size_of_val(&f)); | |
let g = true; | |
println!("g = {}", g); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment