View profile

Rust Programming Fundamentals

Mike Timashov
Mike Timashov
I think it was your deliberate decision to choose Rust. It’s not so popular programming language as JavaScript, or PHP, or Java, or whatever else. But you chose Rust, and I respect your decision.

I can tell you why I started to learn Rust. I decided to develop a decentralized product on the Solana blockchain. The only solution for Solana is Rust. You can actually use C there, but it’s not recommended. So I decided to start learning Rust and I am very happy with it. I want to tell you more about Rust Programming Fundamentals. It took much time for me to find and structurize this info, so if it can help anyone - I would be satisfied.
Cargo is a package manager, build system, test runner, docs generator, etc. It’s like all of the good parts of npm, pip, bundler, and make.
To create a new project, just run:
cargo new hello
To run the project, just run:
cargo run
And to make a release build, run:
cargo run --release
Variables in Rust
To declare a variable, you use “let”
let bunnies = 10;
Or you can use a tuple if you want to declare multiple variables at once.
let (bunnies, carrots) = (10, 50);
Rust has immutable variables by default. I think it’s not actually comfortable to use, but who cares. They tell that it’s for “Safety, Concurrency, and Speed”.
To declare a mutable variable, you should use “let mut”.
let mut bunnies = 10;
bunnies = 20;
Also, you can use constants in Rust. The convention is to use all uppercase words separated with underscores in constants. The type annotation is required. And value must be a constant expression that can be determined at compile time.
const BEST_LANGUAGE_IN_THE_WORLD: &str = "rust";
Memory Safety
Rust guarantees memory safety at compile time. As a part of that, variables must be initiated before you use them.
fn main() {
let x: i32;
println!("{}", x); // Error!
This code will not even compile!
Functions in Rust
fn sum(a: i32, b: i32) -> i32 {
This works fine. If you don’t add the semicolon to the last expression in a block, then it will be returned as the value of the block. This is called the tail expression.
In other words…
{ return true; } and { true } are the same.
Scalar Types
Integer typesUnsigned: u8, u16, u32, u64, u128, usizeSigned: i8, i16, i32, i64, i128, isize
In integer types, underscores are ignored when you define the value. For example, 1000000 and 1_000_000 are the same.
Floating Point types: f32, f64. f64 is the default, but it’s slower than f32.
let x: u16 = 5;
let y: f32 = 3.14;
Booleans are true or false. BOOLEANS ARE NOT INTEGERS. So don’t try to compare them.
Character type. It’s always 4 bytes. Character literals use single quotes. And characters are useless in Rust. Character is not a part of the string.
let my_letter = 'a';
Compound types
let info: (u8, f64, i32) = (1, 3.3, 999);
To access members of a tuple you can use dots syntax.
let jets = info.0;
let fuel = info.1;
let ammo = info.2;
Or get them all at once
let (jets, fuel, ammo) = info;
let buf: [u8; 3] = [1, 2, 3]; // specify values
let buf: [u8; 3] = [1, 3]; // specify the value and the count
Control flow
if num == 5 {
msg = "five";
} else if num == 4 {
msg = "four";
} else {
msg = "other";
And in Rust, we can change this code this way
msg = if num == 5 {
} else if num == 4 {
} else {
How to break out of a nested loop? Easy!
‘loop1: loop {
loop {
loop {
break 'loop1;
while loop is exactly similar.
while should_end_loop() {
// do something
And we can write it like this:
loop {
if !should_end_loop() { break; }
// do something
I prefer “while” loop, but it’s for you to decide what to use.
One more thing here…
“For” loop can take a pattern:
let array = [(1, 2), (3, 4)];
for (x, y) in array.iter() {
// do something with x and y
There are at least 6 types of strings in the Rust std library. But we mostly care about 2 of them.
The first is str. You will probably see it as &str.
let msg = "Hello World";
The second one is String. The data in str can not be modified. But the data in a String, can be modified.
let msg: String = "Hello World".to_string();
let msg: String = String::from("Hello World");
To access the vector of the UTF-8 bytes of a String, you can use
To access chars, use
Ownership in Rust is amazing. It makes Rust so different from other programming languages. And it makes those crazy safety guarantees possible.
It has 3 rules of ownership:
Rule #1. Each value has an owner.
Rule #2. Only one owner of a value.
Rule #3. Value gets dropped if its owner goes out of scope.
let s1 = String::from("abc");
let s2 = s1; // it's not a copy! value is moved.
println!("{}", s1); // Compiler Error!
Reference & Borrowing
let mut s1 = String::from("abc");
do_something(&mut s1); // it borrows the reference to the value
fn do_something(s: &mut String) {
s.insert_str(0, "Hello, ");
Structs (Classes in Rust)
Struct in Rust could have variables, methods, and associated functions.
struct User {
name: String,
email: String,
You can do implementation inside structs.
impl User {
fn new(name: String, email: String) -> Self {
Self {
name: name,
email: email,
let user = User::new(String::from("Mike Timashov"), String::from("[email protected]"));
Inheritance in Rust
It’s going to be a rather short block because there is no inheritance in Rust! So is Rust Object-Oriented language? Good question.
But don’t be in a hurry to stop learning Rust. Continue reading.
Traits (Interfaces in Rust)
Traits in Rust are similar to Interfaces in other languages.
Let’s create a trait.
struct User {
name: String,
email: String,
trait Move {
fn start_moving(&self) -> bool;
impl Move for User {
fn start_moving(&self) -> bool {
Each method of a trait should be implemented.
It’s the most commonly used collection.
let mut v: Vec<i32> = Vec::new();
let x = v.pop(); // x is 6
println!("{}", v[1]); // prints "4"
You can also create a vector much more ergonomic, like this:
let mut v = vec![2, 4, 6];
Vectors have a ton of methods.
HashMap<K, V>
In other languages, you can call it a dictionary.
let mut h: HashMap<u8, bool> = HashMap::new();
h.insert(2, true);
h.insert(7, false);
You must specify a type of Key and a type of Value.
There are a bunch of other collections: VecDequeHashSetLinkedListBinaryHeapBTreeMapBTreeSet. You can read about them in Rust docs. I use them rarely, so I don’t want to waste time here to describe each of them.
Enums in Rust
Enums in Rust are really powerful!
enum Color {
let color = Color::Red;
But the most power from enums in Rust comes from associated data and methods with the variants.
enum SomeItem {
Things(String, u32),
Location {x: i32, y: i32},
use SomeItem::*;
let item = Empty;
let place = Place {x: 0, y: 0};
Isn’t this amazing?
Even better, you can implement methods with an enum.
impl SomeItem {
fn display(&self) {}
And you can use enums with generics.
enum Option<T> {
Closures in Rust
I guess you already know what closures are. I will just show you a few examples of how to use them in Rust.
let add = |x, y| { x + y }
add(1, 2); // returns 3
And another example:
let s = "Hello World".to_string();
let f = move || {
ptintln!("{}", s);
f(); // prints Hello World
Threads in Rust
Here is a fully functional, but empty example of threads in Rust.
use std::thread;
fn main() {
let handle = thread::spawn(move || {
// do stuff in a child thread
// do stuff simultaneously in the main thread
// wait until thread has exited
Final Words
What do you think about this article? Should I write more about my experience with Rust, other programming languages, different platforms, my blockchain experience, etc?
Please write your comments and subscribe to my newsletter.
Did you enjoy this issue? Yes No
Mike Timashov
Mike Timashov @miketimashov

I am an entrepreneur. Write about NFT, Solana, startups, investments, books, technologies.

In order to unsubscribe, click here.
If you were forwarded this newsletter and you like it, you can subscribe here.
Created with Revue by Twitter.