experiments

All kinds of coding experiments
Log | Files | Refs | Submodules

commit 59127d6cd476916f131cfcfcf7de2dab791c9088
parent 04112f46ff71e5df6aea7a26189757f000d4c70c
Author: Vetle Haflan <vetle@haflan.dev>
Date:   Thu, 28 Oct 2021 13:24:30 +0200

Add experiments based on rust-by-example

Diffstat:
Arust/custom_types.rs | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Arust/custom_types2.rs | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Arust/hello_world.rs | 140+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Arust/primitives.rs | 38++++++++++++++++++++++++++++++++++++++
Arust/types.rs | 3+++
5 files changed, 352 insertions(+), 0 deletions(-)

diff --git a/rust/custom_types.rs b/rust/custom_types.rs @@ -0,0 +1,65 @@ +// Custom types +// struct : structure +// enum : enumeration + +// Structs +// Tuple structs : Essentially named tuples, i.e. fields +struct Tuple(i32, i32, i32, i32); +// Classic structs : Named fields, like C +#[derive(Debug)] +struct Classic { + a_field: i32, + b_field: String, +} +// Unit structs : Field-less, useful for generics +struct Unit; + +enum Status { + InSync, + Syncing, + Error, +} + +enum StatusExplicit { + InSync = 1, + Syncing = 2, + Error = 3, +} + +impl Status { + // Instance function + fn print(&self, prefix: String) { + let mut str_status = match self { + Self::InSync => String::from("all good"), + Self::Syncing => String::from("working!"), + Self::Error => String::from("oh no"), + }; + println!("{} {}", prefix, str_status); + } + // Like Java static function + fn get_error() -> Status { + return Status::Error; + } +} + +const STATUS_PREFIX: &str = "It's"; + +fn main() { + let c = Classic { + a_field: 234, + b_field: String::from("Some string"), + }; + println!("{:?}", c); + let t = Tuple(1, 3, 5, 7); + println!("{:?}", t.1); + let s = Status::Syncing; + // Call .print on the instance + s.print(String::from(STATUS_PREFIX)); + // `use`, like used here, makes the `Status::` prefix unnecessary. + // Notice the wildcard to include all instead of individual fields + use crate::Status::*; + InSync.print(String::from("Now it's")); + println!("Implicit discriminator: {}", InSync as i32); + println!("Explicit: {}", StatusExplicit::InSync as i32); + println!("Static function: {}", Status::get_error() as i32) +} diff --git a/rust/custom_types2.rs b/rust/custom_types2.rs @@ -0,0 +1,106 @@ +#[derive(Debug)] +struct Person { + name: String, + age: u8, +} + +// A unit struct +struct Unit; + +// A tuple struct +struct Pair(i32, f32); + +// A struct with two fields +#[derive(Debug)] +struct Point { + x: f32, + y: f32, +} + +// Structs can be reused as fields of another struct +#[derive(Debug)] +#[allow(dead_code)] +struct Rectangle { + // A rectangle can be specified by where the top left and bottom right + // corners are in space. + top_left: Point, + bottom_right: Point, +} + +fn rect_area(r: &Rectangle) -> f32 { + // Nested struct destructuring demonstrated here: + let Rectangle { + top_left: Point { + x: ref x1, + y: ref y1, + }, + bottom_right: Point { + x: ref x2, + y: ref y2, + }, + } = *r; + (x1 - x2) * (y1 - y2) +} + +fn square(p: Point, v: f32) -> Rectangle { + Rectangle { + top_left: Point { x: p.x, y: p.y + v }, + bottom_right: Point { x: p.x + v, y: p.y }, + } +} + +fn main() { + // Create struct with field init shorthand + let name = String::from("Peter"); + let age = 27; + let peter = Person { name, age }; + + // Print debug struct + println!("{:?}", peter); + + // Instantiate a `Point` + let point: Point = Point { x: 10.3, y: 0.4 }; + + // Access the fields of the point + println!("point coordinates: ({}, {})", point.x, point.y); + + // Make a new point by using struct update syntax to use the fields of our + // other one + let bottom_right = Point { x: 5.2, ..point }; + + // `bottom_right.y` will be the same as `point.y` because we used that field + // from `point` + println!("second point: ({}, {})", bottom_right.x, bottom_right.y); + + // Destructure the point using a `let` binding + let Point { + x: left_edge, + y: top_edge, + } = point; + + let _rectangle = Rectangle { + // struct instantiation is an expression too + top_left: Point { + x: left_edge, + y: top_edge, + }, + bottom_right: bottom_right, + }; + + // Instantiate a unit struct + let _unit = Unit; + + // Instantiate a tuple struct + let pair = Pair(1, 0.1); + + // Access the fields of a tuple struct + println!("pair contains {:?} and {:?}", pair.0, pair.1); + + // Destructure a tuple struct + let Pair(integer, decimal) = pair; + + println!("pair contains {:?} and {:?}", integer, decimal); + println!("rect: {:?}", _rectangle); + println!("area: {}", rect_area(&_rectangle)); + println!("rect: {:?}", square(Point { x: 0.0, y: 0.0 }, 3.5)) +} diff --git a/rust/hello_world.rs b/rust/hello_world.rs @@ -0,0 +1,140 @@ +fn main() { + /* + * Formatted print + */ + println!("My name is {0}, {1} {0}", "Bond", "James"); + let pi = 3.141592; + // Implicit position + println!("Pi is roughly {:.2}", pi); + // Explicit position + println!("Pi is roughly {0:.2}", pi); + // Named + println!("Pi is roughly {num:.2}", num = pi); + + /* + * Debug + */ + println!("DEBUG"); + + // v derive(DEBUG) trait lets you use {:?} in println!, but {} though + #[derive(Debug)] + struct Person<'a> { + name: &'a str, + age: u8, + } + let name = "Peter"; + let age = 27; + let peter = Person { name, age }; + + // Pretty print + println!("{:?}", peter); + + /* + * Display + */ + use std::fmt; + // Define a structure where the fields are nameable for comparison. + #[derive(Debug)] + struct Complex { + real: f64, + imag: f64, + } + + // Implement `Display`, which defines how `{}` prints the struct in `println!` + // v derive(DEBUG) trait lets you use {:?} in println!, but {} though + impl fmt::Display for Complex { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // Customize so only `x` and `y` are denoted. + write!(f, "{} + {}i", self.real, self.imag) + } + } + + println!("DISPLAY"); + println!( + "Display: {}", + Complex { + real: 3.3, + imag: 7.2 + } + ); + + println!( + "Debug: {:?}", + Complex { + real: 3.3, + imag: 7.2 + } + ); + + println!("TESTCASE: LIST"); + // Define a structure named `List` containing a `Vec`. + struct List(Vec<i32>); + + impl fmt::Display for List { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // Extract the value using tuple indexing, + // and create a reference to `vec`. + let vec = &self.0; + + write!(f, "[")?; + + // Iterate over `v` in `vec` while enumerating the iteration + // count in `count`. + for (count, v) in vec.iter().enumerate() { + // For every element except the first, add a comma. + // Use the ? operator to return on errors. + if count != 0 { + write!(f, ", ")?; + } + write!(f, "{}: {}", count, v)?; + } + + // Close the opened bracket and return a fmt::Result value. + write!(f, "]") + } + } + let v = List(vec![1, 2, 3]); + println!("{}", v); + + println!("FORMATTING"); + + #[derive(Debug)] + struct Color { + red: u8, + green: u8, + blue: u8, + } + + impl fmt::Display for Color { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "RGB ({0}, {1}, {2}) 0x{0:02X}{1:02X}{2:02X}", + self.red, self.green, self.blue + ) + } + } + for color in [ + Color { + red: 128, + green: 255, + blue: 90, + }, + Color { + red: 0, + green: 3, + blue: 254, + }, + Color { + red: 0, + green: 0, + blue: 0, + }, + ] + .iter() + { + // Switch this to use {} once you've added an implementation + // for fmt::Display. + println!("{}", *color); + } +} diff --git a/rust/primitives.rs b/rust/primitives.rs @@ -0,0 +1,38 @@ +use std::fmt; + +struct Matrix(f32, f32, f32, f32); + +fn transpose(m: Matrix) -> Matrix { + // `let` can be used to bind the members of a tuple to variables + Matrix(m.0, m.2, m.1, m.3) +} + +impl fmt::Display for Matrix { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "( {} {} )\n( {} {} )", self.0, self.1, self.2, self.3) + } +} + +fn main() { + let matrix = Matrix(1.1, 1.2, 2.1, 2.2); + println!("Matrix:\n{}", matrix); + println!("Transpose::\n{}", transpose(matrix)); + + //i = 5; + println!("ARRAYS AND SLICES"); + // Arrays: Fixed length, known at compile time + let arr_five_nums: [i32; 5] = [1, 5, 3, 4, 2]; + let arr_ten_zeros: [i32; 10] = [0; 10]; + println!("{:?}", arr_five_nums); + println!("{:?}", arr_ten_zeros); + // These line will break the build or, if `let i = 5` is moved up, + // lead to panic + //// let i = 5; + //// println!("{}", arr_five_nums[i]); + // + // Slices: Similar to arrays, but length unknown at compile time. + // Essentially consists of (pointer to first element, length) + // Arrays can be automatically borrowed as slices + let slice: &[i32] = &arr_five_nums[1..4]; + println!("{:?}", slice); +} diff --git a/rust/types.rs b/rust/types.rs @@ -0,0 +1,3 @@ +fn main() { + println!("yes"); +}