First I heard about Rust in the summer 2018. Since then I didn’t have much time to run into learning new stuff. I’m glad this is the right time to look at the Rust. This is the reference for Rust language and I’ll try my best to write parts of the language as clear as possible so everyone could understand.
Disclosure: This reference doesn’t cover: lifetimes, threads, generics and other advanced features of the language. This is just a simple reference of syntax of the Rust language.
List of content:
8.1 Ownership
8.2 Borrowing
// unsigned integers
let unsigned_8: u8 = 1; // // from 0 to 255 -> FORMULA: 0 to (2^n)-1
let unsigned_16: u16 = 1; // from 0 to 65536
let unsigned_32: u32 = 1; // from 0 to (2^32)-1
let unsigned_64: u64 = 1; // from 0 to (2^64)-1
let unsigned_128: u128 = 1; // from 0 to (2^128)-1
// signed integers
let signed_8: i8 = 1; // from -128 to 127 -> FORMULA: -(2^(n-1)) to (2^(n-1))-1
let signed_16: i16 = 1; // from -32 768 to 32 767
let signed_32: i32 = 1; // from -(2^31) to (2^31-1)
let signed_64: i64 = 1; // from -(2^63) to (2^63-1)
let signed_128: i128 = 1; // from -(2^127) to (2^127-1)
// lets get real here
let floated_32bit: f32 = 2.0;
let floated_64bit: f64 = 2.0;
// bools
let b: bool = true;
// static string - compile time strings
let static_string: &str = "hello world";
// dynamic strings
let std_string: String = String::new("Hello world");
// vectors
let num_vec: Vec<i32> = vec![1, 2, 3]; // vec! is macro for creating Vec
if age > 17 {
println!("Okay, now you can drink alcohol");
} else {
println!("Sorry, alcohol is for people older than 18...");
}
let condition = true;
let variable = if condition {
// 1 is assigned to variable if condition is true
1
} else {
// 0 is assigned to variable if condition is false
0
}
let mut number = 0;
while number < 10 {
println!("{}!", number);
number = number + 1;
}
loop {
println!("forever!");
}
let a = [10, 20, 30, 40, 50];
for element in a.iter() {
println!("the value is: {}", element);
}
let x = 5; // type - immutable integer variable
let mut y: i8; // mutable integer variable - signed mutable variable
// all variables without "mut" are immutable by default
// if variables are declared with "mut" identifier, you can mutate
// these variables
let mut year = 2018;
year = 2019; // OK
// code below can't be mutated
let immutable = 5;
immutable = 10; // ERROR !!!!
fn sum_two_numbers(a: i32, b: i32) -> i32 {
return a + b;
}
// OR
// valid returning without return statement
// see there is no semicolon ;
fn sum_two_numbers(a: i32, b: i32) -> i32 {
a + b
}
fn main() {
let increment = 5;
let increment_by = |x: i32| x + increment;
println!("increment 5 + 5 is {}", increment_by(5));
// OUTPUT: increment 5 + 5 is 10
}
enum Color {
Transparent,
RGB(u8, u8, u8),
RGBA(u8, u8, u8, f32),
Brown,
Blue,
}
fn main() {
let kinda_red = Color::RGBA(255, 0, 0, 0.5);
match kinda_red {
Color::Transparent => println!("This color is transparent"),
Color::RGB(r, g, b) => println!("RGB color with {} red, {} green, {} blue", r, g, b),
Color::RGBA(r, g, b, a) => println!("RGBA colors {},{},{} transparency = {}", r, g, b, a),
_ => println!("Other cases: Brown or Blue"), // in other languages: Default
};
// We must cover all enum cases, because compiler gonna have problem with that.
}
struct Person {
first_name: String,
last_name: String,
age: u32,
address: String,
}
fn main() {
let me = Person{
first_name: "Martin".to_string(),
last_name: "Schnurer".to_string(),
age: 23,
address: "Some address".to_string(),
};
println!(
"I am {} {}, I am {} years old and I live at {}",
me.first_name,
me.last_name,
me.age,
me.address
);
//OUTPUT: I am Martin Schnurer, I am 23 years old and I live at Some address
}
struct Person {
first_name: String,
last_name: String,
age: u32,
address: String,
}
impl Person {
fn find_girlfriend(self: &Self, with_name: String) {
println!("Hi I am {} {} and I am looking for a girl with name {}",
self.first_name,self.last_name, with_name);
}
}
fn main() {
let me = Person{
first_name: "Martin".to_string(),
last_name: "Schnurer".to_string(),
age: 23,
address: "Some address".to_string(),
};
me.find_girlfriend("Monica".to_string());
// OUTPUT: Hi I am Martin Schnurer and I am looking for a girl with name Monica
}
struct Person{ age: u16 }
fn write_age(person: Person) {
println!("This person is {} years old", person.age);
}
fn is_adult(person: Person) -> bool {
person.age > 17
}
fn main() {
let john = Person{age: 23};
write_age(john); // OK: This person is 23 years old (ownership passed to the write_age function)
// write_age is out of scope and john variable will be deleted there
let john_is_adult = is_adult(john); // COMPILATION FAIL, variable john was moved to the write_age fn
// we can't use variable.
}
After the ownership (variable) is moved into another scope, you can’t use this variable in the scope. See above how we tried to use john variable passing into is_adult function - this will not compile, because we moved ownership of john to the write_age function scope and after write_age is done (out of scope), the content of the john variable is deleted.
struct Person{ age: u16 }
fn write_age(person: Person) -> Person {
println!("This person is {} years old", person.age);
return person // Now we move back the ownership from the function
}
fn is_adult(person: Person) -> bool {
person.age > 17
}
fn main() {
let john = Person{age: 23};
let john = write_age(john); // OK: This person is 23 years old (ownership passed to the write_age function)
// ownership is moved back from the write_age to the john, we can use john again
let john_is_adult = is_adult(john); // OK
println!("john is adult = {}", john_is_adult); // OK
}
Passing and returning ownerships is not always best decision to do - code overhead,
struct Person{ age: u16 }
fn write_age(person: &Person) { // Not returning ownership anymore
println!("This person is {} years old", person.age);
}
fn is_adult(person: &Person) -> bool {
person.age > 17
}
fn main() {
let john = Person{age: 23};
write_age(&john); // OK: passing reference
let john_is_adult = is_adult(&john); // OK, passing reference
println!("john is adult = {}", john_is_adult);
}
When we want to pass a reference to another scope and we want also alter this passed variable - then we need to pass this with keyword &mut - mutable reference.
struct Person{ age: u16 }
fn increment_age(person: &mut Person) {
person.age += 1;
}
fn main() {
let mut john = Person{age: 23}; // we need to mark john as mutable as the function will mutate our passed variable
increment_age(&mut john); // instead of &john we pass &mut john
}
The one reason rust convinced me to look deeper at it was the claim that we can write rust in completely safe manner without garbage collection - completely dependant on the out of a scope garbage collection. I haven’t written anything serious in rust - but I had the feeling that the compiler was a real dictator here didn’t allow me easily do whatever I want - but when it does, I had a good feeling about compiled code and large amount of executions of the code was bug free and has run as expected - without panicking.
On the other side, I had serious problem to get used to traits and lifetimes. I didn’t referenced lifetimes above, because I assume them to be more difficult to learn and as I wanted to let this reference as simple as possible - I didn’t describing them here (but it doesn’t mean I won’t describe them in another post later).
In C language, you probably didn’t have a problem to easily implement linked list. Well, good luck with trying that in Rust. Linked list is pretty all about pointers and pointer checking. Rust is pretty good at controlling (Borrow checker) what exactly are you doing with pointers and memory - and if you do something unsafe, it won’t compile.
I found this article to deeply describe linked list implementation in Rust. Have fun.
If you want to read full documentation and rust reference - go here.
In the last part How To Use Redux Without Losing Your Mind I’ve presented the new way of using redux libary. The main reason behind…
TLDR; You can use redux without a lot of boilerplate with just one action changing the whole reducer state. Consistency of the structure can…
Introduction It’s going to be a while working as a web developer in this crazy fast growing and emerging industry. Next to the web…