Memory + Static Type Systems
Why do modern computers have different types of memory?
| Memory Type | Typical Size | Typical access time | |
|---|---|---|---|
| Register | A few bytes | One CPU cycle (less than a nanosecond) | |
| L1 Cache | Dozens of KiBs | A few CPU cycles (about a nanosecond) | |
| L2 Cache | Hundreds of KiBs | ~10ns | |
| L3 Cache | A few MiBs | 20-40ns | |
| Main Memory | GiBs | 100-300ns | |
| SSD | TiBs | A few hundred microseconds | |
| HDD | Dozens of TiBs | A few milliseconds | |
| Network Storage | Up to Exabytes | Hundreds of milliseconds to seconds |
push and pop statementspush and pop (if your compiler is smart)fn main() {
let mut input = String::new();
let mut numbers = ???;
loop {
println!("Insert a number or leave empty to finish:");
std::io::stdin().read_line(&mut input)
.expect("Failed to read input");
if input.is_empty_or_whitespace() {
break;
}
let number = input.parse::<i32>().expect("invalid value");
numbers.push(number);
}
numbers.sort();
println!("{numbers}");
}fn main() {
let mut input = String::new();
let mut numbers = ???;
loop {
println!("Insert a number or leave empty to finish:");
std::io::stdin().read_line(&mut input)
.expect("Failed to read input");
if input.is_empty_or_whitespace() {
break;
}
let number = input.parse::<i32>().expect("invalid value");
numbers.push(number);
}
numbers.sort();
println!("{numbers}");
}String be?const MAX_STRING_LEN: usize = 256;
const MAX_NUMBERS: usize = 128;
fn stoi(bytes: &[u8]) -> i32 { todo!() }
fn main() {
let mut input: [u8; _] = [0; MAX_STRING_LEN];
let mut input_size: usize = 0;
let mut numbers: [i32; _] = [0; MAX_NUMBERS];
let mut numbers_size: usize = 0;
loop {
println!("Insert a number or leave empty to finish:");
input_size = std::io::stdin()
.read(&mut input)
.expect("Failed to read input");
if input_size == 0 {
break;
}
let number = stoi(&input[..input_size]);
numbers[numbers_size] = number;
numbers_size += 1;
}
numbers.sort();
println!("{:?}", &numbers[..numbers_size]);
}fn main() {
let mut input = String::new();
let mut numbers = Vec::new();
loop {
println!("Insert a number or leave empty to finish:");
std::io::stdin().read_line(&mut input)
.expect("Failed to read input");
if input.is_empty_or_whitespace() {
break;
}
let number = input.parse::<i32>().expect("invalid value");
numbers.push(number);
}
numbers.sort();
println!("{numbers}");
}Vec<T>Vec<T> (or std::vector<T> in C++) manages a dynamic piece of memory
numbers goes out of scope at the end of mainfn main() {
let mut input = String::new();
let mut numbers = Vec::new();
loop {
println!("Insert a number or leave empty to finish:");
std::io::stdin().read_line(&mut input)
.expect("Failed to read input");
if input.is_empty_or_whitespace() {
break;
}
let number = input.parse::<i32>().expect("invalid value");
numbers.push(number); // Will allocate
}
numbers.sort();
println!("{numbers}");
}Drop trait - Destructors in RustVec<T> owns a dynamic array on the heapString also owns a dynamic array (of UTF-8 bytes) on the heapFile owns a file handle from the OSDrop trait - ExampleDrop trait - Exampledrop callfree/delete anymore!
borrow of moved value: `numbers`
print_numbers(numbers)Copy traitCopy for types that support bitwise copies
CopyCopy turns moves into copiesCopy?Clone traitClone trait!Copy, Clone, moving and pinningCome up with a Copy + Clone type, a Clone type, and a move-only type
Work in groups, duplicated types cancel out!