Skip to content

Instantly share code, notes, and snippets.

@miguelcnf
Last active August 14, 2020 18:01
Show Gist options
  • Save miguelcnf/ce44b7fe4655194bf6bde5081c759cdd to your computer and use it in GitHub Desktop.
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
#![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