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
Common Collections
Storing Lists of Values with VectorsThe first collection type we’ll look at is
Vec<T>
, also known as a vector. Vectors allow you to store more than one value in a single data structure that puts all the values next to each other in memory. Vectors can only store values of the same type. They are useful when you have a list of items, such as the lines of text in a file or the prices of items in a shopping cart.Creating a New Vector
let v: Vec<i32> = Vec::new();
Note that we added a type annotation here. Because we aren’t inserting any values into this vector, Rust doesn’t know what kind of elements we intend to store. This is an important point. Vectors are implemented using generics; we’ll cover how to use generics with your own types.
In more realistic code, Rust can often infer the type of value you want to store once you insert values, so you rarely need to do this type annotation. It’s more common to create a
Vec<T>
that has initial values, and Rust provides the vec! macro for convenience.
let v = vec![1, 2, 3];
Because we’ve given initial i32 values, Rust can infer that the type of v is Vec<i32>, and the type annotation isn’t necessary. Next, we’ll look at how to modify a vector.
Updating a Vector
let mut v = Vec::new();
v.push(5);
v.push(6);
v.push(7);
v.push(8);
v.push(5);
v.push(6);
v.push(7);
v.push(8);
Dropping a Vector Drops Its Elements
{
let v = vec![1, 2, 3, 4];
// do stuff with v
} // <- v goes out of scope and is freed here
let v = vec![1, 2, 3, 4];
// do stuff with v
} // <- v goes out of scope and is freed here
When the vector gets dropped, all of its contents are also dropped, meaning those integers it holds will be cleaned up.
Reading Elements of Vectors
Example shows both methods of accessing a value in a vector, either with indexing syntax or the
get
method. let v = vec![1, 2, 3, 4, 5];
let third: &i32 = &v[2];
println!("The third element is {}", third);
match v.get(2) {
Some(third) => println!("The third element is {}", third),
None => println!("There is no third element."),
}
let third: &i32 = &v[2];
println!("The third element is {}", third);
match v.get(2) {
Some(third) => println!("The third element is {}", third),
None => println!("There is no third element."),
}
Output:
The third element is 3
The third element is 3
Panic!
let v = vec![1, 2, 3, 4, 5];
let does_not_exist = &v[100];
let does_not_exist = v.get(100);
let does_not_exist = &v[100];
let does_not_exist = v.get(100);
Attempting to access the element at index 100 in a vector containing five elements
Panic!
let mut v = vec![1, 2, 3, 4, 5];
let first = &v[0];
v.push(6);
println!("The first element is: {}", first);
let first = &v[0];
v.push(6);
println!("The first element is: {}", first);
Attempting to add an element to a vector while holding a reference to an item
Iterating over the Values in a Vector
let v = vec![100, 32, 57];
for i in &v {
println!("{}", i);
}
We can also iterate over mutable references to each element in a mutable vector in order to make changes to all the elements.
fn main() {
let mut v = vec![100, 32, 57];
for i in &mut v {
*i += 50;
}
}
let mut v = vec![100, 32, 57];
for i in &mut v {
*i += 50;
}
}
To change the value that the mutable reference refers to, we have to use the dereference operator (*) to get to the value in i before we can use the += operator.
fn main() {
let mut v = vec![100, 32, 57]; // [100, 32, 57]
println!("{:?}", v);
for i in &mut v {
*i += 50;
}
println!("{:?}", v); // [150, 82, 107]
}
let mut v = vec![100, 32, 57]; // [100, 32, 57]
println!("{:?}", v);
for i in &mut v {
*i += 50;
}
println!("{:?}", v); // [150, 82, 107]
}
Using an Enum to Store Multiple Types
At the beginning of this chapter, we said that vectors can only store values that are the same type. This can be inconvenient; there are definitely use cases for needing to store a list of items of different types. Fortunately, the variants of an enum are defined under the same enum type, so when we need to store elements of a different type in a vector, we can define and use an enum!
fn main() {
enum SpreadsheetCell {
Int(i32),
Float(f64),
Text(String),
}
let row = vec![
SpreadsheetCell::Int(3),
SpreadsheetCell::Text(String::from("blue")),
SpreadsheetCell::Float(10.12),
];
}
enum SpreadsheetCell {
Int(i32),
Float(f64),
Text(String),
}
let row = vec![
SpreadsheetCell::Int(3),
SpreadsheetCell::Text(String::from("blue")),
SpreadsheetCell::Float(10.12),
];
}