enum Option<T> {
Some(T),
None,
}There several pervasive types in Rust.
They leverage the powerful type system to accomplish fundamental tasks.
Option<T> - Removes the need for a null primitive.
Result<T,E> - Removes the need for exceptions.
Vec<T> - Growable arrays.
HashMap<K,V> - Key value storage.
Option<T>enum Option<T> {
Some(T),
None,
}Options are wrapper types, and need to be unwrapped to be used.
Option<T>Any function which does not always return a value returns an Option<T>.
fn main() {
let values = vec![1, 2, 3];
println!("{:?}", values.get(0)); // Some(1)
println!("{:?}", values.get(4)); // None
}Option<T>: BenefitThe programmer always knows where a None may appear, and is able to decide how the situation should be handled.
This characteristic helps remove mystery from the coding process, and aids in confidence.
Option<T>: Unwrappingunwrap() will panic the application if the value is None.
This is only recommended in testing and prototyping.
fn main() {
let nothing: Option<usize> = None;
nothing.unwrap();
}Option<T>: Safetymatch is one of several ways to safety work with `Option`s.
fn main() {
let maybe_a_value = Some(1);
match maybe_a_value {
Some(v) => println!("{}", v),
None => println!("None"),
}
}No matter what the value of maybe_a_value, the program will never crash.
Option<T>: QuestionsDoes this type completely remove the need for a null primitive?
What are the benefits?
Result<T,E>enum Result<T,E> {
Ok(T),
Err(E),
}Results are wrapper types which either contain the successful value, or the error value.
Result<T,E>: UsingResults can be handled via unwrap() just like Option types, and can be handled in the same ways.
fn main() {
if let Err(e) = File::open("nein") {
println!("{:?}", e);
}
}Handling complex error scenarios will be addressed in a later chapter.
Result<T,E>: QuestionsDoes this type completely remove the need for exceptions?
What are the benefits?
Vec<T>Owned, mutable, growable arrays. Located on the heap.
struct Vec<T> {
items: T,
length: usize,
capacity: usize,
}Vec<T>: CreationCreate with Vec::new() or the vec![] macro.
fn main() {
let explicit_type = Vec::<usize>::new();
let mut implicit_type = Vec::new();
implicit_type.push(1);
let macro_created = vec![1, 2, 3];
}Vec<T>: As a SliceVec<T> implements Deref<Target=[T]>, so it can be easily used as a slice.
fn main() {
let items = vec![1, 2, 3];
let ref_to_items: &[usize] = &items;
}HashMap<K,V>HashMaps are key value stores. Keys must implement Hash.
use std::collections::HashMap;
fn main() {
let mut kv_store = HashMap::new();
kv_store.insert("key", true);
println!("{}", kv_store.get("key"));
}HashMap<K,V>: entry()Manipulate a key’s cooresponding entry in place.
use std::collections::HashMap;
fn main() {
let mut kv_store = HashMap::new();
let mut value = kv_store.entry("key").or_insert(true);
*value = false;
}