finished ch8.1

This commit is contained in:
darkicewolf50 2025-01-17 20:51:38 -07:00
parent 40a722d93d
commit 1624bbb975
6 changed files with 193 additions and 18 deletions

3
.obsidian/app.json vendored
View File

@ -1,4 +1,5 @@
{ {
"promptDelete": false, "promptDelete": false,
"alwaysUpdateLinks": true "alwaysUpdateLinks": true,
"useMarkdownLinks": false
} }

View File

@ -13,12 +13,12 @@
"state": { "state": {
"type": "markdown", "type": "markdown",
"state": { "state": {
"file": "data_types.md", "file": "ownership.md",
"mode": "source", "mode": "source",
"source": false "source": false
}, },
"icon": "lucide-file", "icon": "lucide-file",
"title": "data_types" "title": "ownership"
} }
}, },
{ {
@ -27,12 +27,12 @@
"state": { "state": {
"type": "markdown", "type": "markdown",
"state": { "state": {
"file": "Modules and Use.md", "file": "Vector.md",
"mode": "source", "mode": "source",
"source": false "source": false
}, },
"icon": "lucide-file", "icon": "lucide-file",
"title": "Modules and Use" "title": "Vector"
} }
}, },
{ {
@ -41,16 +41,16 @@
"state": { "state": {
"type": "markdown", "type": "markdown",
"state": { "state": {
"file": "Collection of Common Data Structs.md", "file": "data_types.md",
"mode": "source", "mode": "source",
"source": false "source": false
}, },
"icon": "lucide-file", "icon": "lucide-file",
"title": "Collection of Common Data Structs" "title": "data_types"
} }
} }
], ],
"currentTab": 2 "currentTab": 1
} }
], ],
"direction": "vertical" "direction": "vertical"
@ -192,14 +192,16 @@
"command-palette:Open command palette": false "command-palette:Open command palette": false
} }
}, },
"active": "b6a35c226bb40634", "active": "b80f5219fa24358f",
"lastOpenFiles": [ "lastOpenFiles": [
"Modules and Use.md",
"Collection of Common Data Structs.md", "Collection of Common Data Structs.md",
"Packages.md", "Vector.md",
"data_types.md", "data_types.md",
"Crates.md", "Modules and Use.md",
"ownership.md",
"Project Organization.md", "Project Organization.md",
"Packages.md",
"Crates.md",
"crates.io.md", "crates.io.md",
"Paths.md", "Paths.md",
"does_not_compile.svg", "does_not_compile.svg",
@ -211,7 +213,6 @@
"Good and Bad Code/Commenting Pratices", "Good and Bad Code/Commenting Pratices",
"Good and Bad Code", "Good and Bad Code",
"Data Types.md", "Data Types.md",
"ownership.md",
"Variables.md", "Variables.md",
"README.md", "README.md",
"Constants.md" "Constants.md"

View File

@ -1 +1,19 @@
# Collection of Common Data Structs # Collection of Common Data Structs
The std library includes a number of useful data structures called collections
Collections can contain multiple values unlike built in array and tuples types these are all stored on the heap which means the amount of data does not need to be known at compile time and can grow or shrink as the program runs
each kind of collection has different capabilities and cost
choosing the right one is a skill that is developed over time
## Common Collections
- [*Vector*](Vector.md) - allows for storing a variable number of values next to each other
- [*String*](String.md) - a collection of characters
- *Hash Map* - allows you to associate a value with a specific key
- Its particular implementation is a more general version of a general data struct called a map
- {
- 1: data,
- 2: more_data,
- 3: this is a map
- }

156
Vector.md Normal file
View File

@ -0,0 +1,156 @@
# Vector
Vectors allow you to store more and one value in a single data structure that puts all of the values next to each other in the memory
Vectors can only store values of the same type hence the generic in the ``Vec<T>`` keyword
useful when you have a list of items, like the lines of text in a file or the prices of items in a shopping cart (this would be better with a hash map (more obj relation))
## Creating a new Vector
to create a empty vector we call
``let v: Vec<i32> = Vec::new();``
Type annotation is need because a value is not given here and the compiler will not know what type of data will be stored here
hence why the generic must be specified instead of inferred
More often a Vector will have initial values and Rust will infer the type of value stored
Rust has a Macro for this ``vec!``
this will create a new vector that holds the values given to it
```rust
let v = vec![1, 2, 3];
```
this is implicitly a ``Vec<i32>``
## Updating a Vector
Add values to the vector you can use the push method
```rust
let mut v = Vec::new();
v.push(5);
v.push(6);
v.push(7);
v.push(8);
```
This must be mutable in order to do this
this is another way to implicitly start up a ``Vec<i32>`` variable
## Reading Elements of Vectors
There a two ways to reference a value sorted in a vector
via indexing or by using the ``get`` method
here is an example of using both
```rust
let v = vec![1, 2, 3, 4, 5];
let third: &i32 = &v[2];
println!("The third element is {third}");
let third: Option<&i32> = v.get(2);
match third {
Some(third) => println!("The third element is {third}"),
None => println!("There is no third element."),
}
```
this uses the index of 2 to get the third element
vectors are indexed starting at zero
using ``&`` and ``[]`` gives us a reference to the element at the index value
when using get it returns an ``Option<&T>`` which is a referenced generic which is then specified to a i32
as you can see the ``get`` method is more safe because it accounts for when it way be null value or out of range
```rust
let does_not_exist = &v[100];
let does_not_exist = v.get(100);
```
the first one would cause the program to panic but the second wouldn't cause a panic instead it would require the situation to be dealt with in a match pattern for when it is None
see [``Option<T>``](data_types.md#The Option Enum and Advantages over Null types) for more details
when the program has a valid reference the borrow checker ensures this reference and any other references must be valid to the contents of where it refers to.
One case where this could easily be broken is creating a reference then trying to add an element to the end then trying to use the reference later in the function
<img style="height:5svh" src="https://doc.rust-lang.org/book/img/ferris/does_not_compile.svg" />
```rust
let mut v = vec![1, 2, 3, 4, 5];
let first = &v[0];
v.push(6);
println!("The first element is: {first}");
```
this would result in a borrow checker error
because vector.push uses a mutable reference to the vector
check here for more details [[ownership#Rules]]
This is also due to how vectors are implemented, what happens when the allocated space on memory runs out, then it must be copied to another place in memory, then the old vector is freed
In that case where the reference is pointing to may be deallocated and therefore not valid
For implementation details of ``Vec<T>`` type see [The Rustonomicon](https://doc.rust-lang.org/nomicon/vec/vec.html)
## Iterating Over the Values in a Vector
We would rather iterate over the elements rather than over the index ands access each one one at a time
here is an example that give an immutable reference for each element
```rust
let v = vec![100, 32, 57];
for i in &v {
println!("{i}");
}
```
can also iterate over mutable referneces
here is an example where we add 50 to each element using the ``*`` or dereference operator to assign values to the reference
```rust
let mut v = vec![100, 32, 57];
for i in &mut v {
*i += 50;
}
```
We cannot add or remove from the vector when iterating over it because of borrow checking rules, the reference to the whole vector prevents that
## Using an Enum to Store Multiple Types
Vectors can only store values that are of the same type, this can be inconvenient sometimes.
But you can use variants of an enum which is considered the same type
this is allowed
```rust
enum SpreadsheetCell {
Int(i32),
Float(f64),
Text(String),
}
let row = vec![
SpreadsheetCell::Int(3),
SpreadsheetCell::Text(String::from("blue")),
SpreadsheetCell::Float(10.12),
];
```
Rust needs to know what types will be in the vector at compile time so it knows exactly how much memory to store per element in the vector so it must be specific when initializing a vector
using an enum plus a match ensures that all possible cases are handled which ensures that a panic will not happen
If you do not know the exhaustive set of types a program will get at runtime to store in a vector then the enum technique will not work instead use a trait object
Here is a the API documentation for a Vector with all of the methods defined on a ``Vec<T>``
For example a ``pop`` removes and returns the last element
## Dropping a Vector Drops Its Elements
This is like any other struct, when a vector is freed/goes out of scope then so will its inner elements

View File

@ -718,7 +718,7 @@ can implement behavior in relation to an enum
## The Option Enum and Advantages over Null types ## The Option Enum and Advantages over Null types
this is a specail case where the variants are nothing nas something this is a special case where the variants are nothing nas something
this is part of the standard library can can be included this is part of the standard library can can be included
this should be handled so that the compiler can check for handling all types this should be handled so that the compiler can check for handling all types
@ -727,9 +727,9 @@ this then handle the case of what if it is empty
a feature of rust is excluding null references a feature of rust is excluding null references
if you try to use a null value as a not null value you get an error if you try to use a null value as a not null value you get an error
this is due to null or not null as pervasive and extrememly easy to make this kind of error this is due to null or not null as pervasive and extremely easy to make this kind of error
null is still useful for expressing a vlaue that is not present or not valid for some reason null is still useful for expressing a value that is not present or not valid for some reason
this is a problem of implementation this is a problem of implementation
rust doesnt have nulls but can be expressed as the enum Option<T> rust doesnt have nulls but can be expressed as the enum Option<T>

View File

@ -106,8 +106,7 @@ fn calculate_length(s: String) -> (String, usize) {
# References # References
## Rules ## Rules
1. At any given time, you can have either one mutable reference or any number of 1. At any given time, you can have either one mutable reference or any number of immutable references.
immutable references.
1. References must always be valid 1. References must always be valid
Giving access to a variable without transfering ownership/moving it Giving access to a variable without transfering ownership/moving it