Index
- Guessing Game
- Common Programming Concepts
- Understanding Ownership
- Using Structs
- Enums and Pattern Matching
- Managing Growing Projects with Packages, Crates, and Modules
- Defining Modules to Control Scope and Privacy
- Paths for Referring to an Item in the Module Tree
- Bringing Paths into Scope with the use Keyword
- Separating Modules into Different Files
- Common Collections
- Error Handling
- Generic Types, Traits, and Lifetimes
- Writing Automated Tests
- Object Oriented Programming
- Adding dependancies
- Option Take
- RefCell
- mem
- Data Structure
- Recipe
- Semi colon
- Calling rust from python
- Default
- Crytocurrency With rust
- Function chaining
- Question Mark Operator
- Tests with println
- lib and bin
- Append vector to hash map
- Random Number
- uuid4
- uwrap and option
- Blockchain with Rust
- Near Protocol
- Actix-web
Data Types
Probing Questions:When you have to add type annotation?
Data Types
Keep in mind that Rust is a statically typed language, which means that it must know the types of all variables at compile time.
In cases when many types are possible, such as when we converted a
String
to a numeric type using parse
we must add a type annotation#![allow(unused_variables)]
fn main() {
let guess: u32 = "42".parse().expect("Not a number!");
}
fn main() {
let guess: u32 = "42".parse().expect("Not a number!");
}
Scalar Types
A scalar type represents a single value. Rust has four primary scalar types: integers, floating-point numbers, Booleans, and characters.
Integer Types
This type declaration indicates that the value it’s associated with should be an unsigned integer (signed integer types start with
i
, instead of u
) that takes up 32 bits of spaceEach signed variant can store numbers from -(2n - 1) to 2n - 1 - 1 inclusive, where n is the number of bits that variant uses. So an
i8
can store numbers from -(27) to 27 - 1, which equals -128 to 127. Unsigned variants can store numbers from 0 to 2n - 1, so a u8
can store numbers from 0 to 28 - 1, which equals 0 to 255.So how do you know which type of integer to use? If you’re unsure, Rust’s defaults are generally good choices, and integer types default to
i32
: this type is generally the fastest, even on 64-bit systems.• Check about Integer Overflow from book
Floating-Point Types
Rust also has two primitive types for floating-point numbers, which are numbers with decimal points. Rust’s floating-point types are
f32
and f64
, which are 32 bits and 64 bits in size, respectively. The default type is f64
because on modern CPUs it’s roughly the same speed as f32
but is capable of more precision.fn main() {
let x = 2.0; // f64
let y: f32 = 3.0; // f32
}
let x = 2.0; // f64
let y: f32 = 3.0; // f32
}
Numeric Operations
fn main() {
// addition
let sum = 5 + 10;
// subtraction
let difference = 95.5 - 4.3;
// multiplication
let product = 4 * 30;
// division
let quotient = 56.7 / 32.2;
// remainder
let remainder = 43 % 5;
}
// addition
let sum = 5 + 10;
// subtraction
let difference = 95.5 - 4.3;
// multiplication
let product = 4 * 30;
// division
let quotient = 56.7 / 32.2;
// remainder
let remainder = 43 % 5;
}
The Boolean Type
fn main() {
let t = true;
let f: bool = false; // with explicit type annotation
}
let t = true;
let f: bool = false; // with explicit type annotation
}
The Character Type
(Note that
char
literals are specified with single quotes, as opposed to string literals, which use double quotes.)fn main() {
let c = 'z';
let z = 'ℤ';
let heart_eyed_cat = '😻';
}
let c = 'z';
let z = 'ℤ';
let heart_eyed_cat = '😻';
}
Rust’s
char
type is four bytes in size and represents a Unicode Scalar ValueCompound Types
Compound types can group multiple values into one type. Rust has two primitive compound types: tuples and arrays.
The Tuple Type
We create a tuple by writing a comma-separated list of values inside parentheses. Each position in the tuple has a type, and the types of the different values in the tuple don’t have to be the same. We’ve added optional type annotations in this example:
fn main() {
let tup: (i32, f64, u8) = (500, 6.4, 1);
}
let tup: (i32, f64, u8) = (500, 6.4, 1);
}
To get the individual values out of a tuple, we can use pattern matching to destructure a tuple value, like this
fn main() {
let tup = (500, 6.4, 1);
let (x, y, z) = tup;
println!("The value of y is: {}", y); // The value of y is: 6.4
}
let tup = (500, 6.4, 1);
let (x, y, z) = tup;
println!("The value of y is: {}", y); // The value of y is: 6.4
}
In addition to destructuring through pattern matching, we can access a tuple element directly by using a period (
.
) followed by the index of the value we want to access. For example:fn main() {
let x: (i32, f64, u8) = (500, 6.4, 1);
let five_hundred = x.0;
let six_point_four = x.1;
let one = x.2;
}
let x: (i32, f64, u8) = (500, 6.4, 1);
let five_hundred = x.0;
let six_point_four = x.1;
let one = x.2;
}
The Array Type
Unlike a tuple, every element of an array must have the same type. Arrays in Rust are different from arrays in some other languages because arrays in Rust have a fixed length, like tuples
fn main() {
let a = [1, 2, 3, 4, 5];
}
let a = [1, 2, 3, 4, 5];
}
An array isn’t as flexible as the vector type, though. A vector is a similar collection type provided by the standard library that is allowed to grow or shrink in size.
A month example:
It’s very unlikely that such a program will need to add or remove months, so you can use an array because you know it will always contain 12 elements:
let months = ["January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December"];
You would write an array’s type by using square brackets, and within the brackets include the type of each element, a semicolon, and then the number of elements in the array, like so:
let a: [i32; 5] = [1, 2, 3, 4, 5];
Writing an array’s type this way looks similar to an alternative syntax for initializing an array: if you want to create an array that contains the same value for each element, you can specify the initial value, followed by a semicolon, and then the length of the array in square brackets, as shown here:
let a = [3; 5];
The array named
a
will contain 5
elements that will all be set to the value 3
initially. This is the same as writing let a = [3, 3, 3, 3, 3];
but in a more concise way.Accessing Array Elements
An array is a single chunk of memory allocated on the stack. You can access elements of an array using indexing, like this:
fn main() {
let a = [1, 2, 3, 4, 5];
let first = a[0];
let second = a[1];
}
let a = [1, 2, 3, 4, 5];
let first = a[0];
let second = a[1];
}