about
05/04/2022
RustBites - Facts
Code Repository Code Examples Rust Bites Repo

Rust Bite - Facts

common terms

The table, below, summarizes things we've learned in the Rust Bytes so far and adds a few more things to come. Occasionally terms like "object" and "trait" are used with their intuitive meanings. In later Bites we will give them, e.g., object and trait precise meanings.
Data Operations
Copy type - holds no resources in the heap.
User-defined types must implement std::marker::Copy trait.
Examples:
bool, char, i32, ... u8, ... f32, ...
[i32;N], (i32, f64), struct { i32, f64 }
Move type - holds resources in the heap
Cannot implement copy trait.
Examples:
String, Vec<T>, Map<K, V>, ...
[String;N], (i32, Vec<f64>), struct { i32, String }
Bind - associates an identifier with a value.
This creates a new instance.
Examples:
let i:i32 = 3;
let j = i;
let s = String::new();
Copy - copies value associated with an identifier.
- This applies to both binds and assignments for Copy types.
- Invoked implicitly by compiler generated code.
- Source of copy is valid after copy.
Examples:
let i:i32 = 3;
let j = i;
i = j;
Move - moves resources from one instance to another.
- This applies to both binds and assignments for Move types.
- Invoked implicitly by compiler generated code.
- Source of move is invalid after move.
Examples:
let s = String::from("a string");  // bind
let t = s;  // move and bind
Clone - creates instance with copy of resources of cloned.
- Invoked explicitly by developer code.
- Source is valid after clone operation.
- Source type must implement Clone trait.
Examples:
let s = String::from("a string");
let t = s.clone();  // clone
Drop - returns resources when owner goes out of scope.
- This applies only to Move types.
- Invoked implicitly by compiler generated code.
- Can be invoked explicitly by program code.
Example:
let s = String::from("a string");
std::mem::drop(s);
 
 
Data Structures
Array - Contiguous set of values all of the same type.
- Indexable
- Fixed number of elements
Examples:
let a: [3; i32] = [1, 2, 3]; // static memory
let b = Box::new([0;3]); // heap memory
String - Contiguous collection of utf-8 chars.
- Not indexable
- Iterable
- Expandable
Examples:
let s: String = String::new();
let t = String::from("a literal string");
Vec<T> - Contiguous set of values all of the same type.
- Indexable
- Expandable number of elements
- May reallocate
Examples:
let v: Vec<i32> = vec![1, 2, 3];
let w = Vec::<i32>::new();
HashMap<K, V> - Table of buckets (list of key/value pairs).
- Accessed by hash of key:K
- Each key has associated value v:V
- Add with insert, delete with remove
Examples:
let m = HashMap::<String, Widget>::new();
let v = m[k];
 
Smart Pointers
Box - Point to data on heap.
- Drop returns resource (when leaving scope)
- Auto DeRef supports methods of referend
Examples:
let d = Box::<String>::new("a string".to_string());
let b = Box::new(Point { x:1.0, y:1.5, z:-0.5 }
RefCell - Defer ownership checking to run-time.
- borrow() to view inner
- borrow_mut() gives mutable access to inner - will panic if safety invariants are not satisfied
Examples:
let sp = RefCell::new(String>::new("a string".to_string()));
let r = sp.borrow_mut();
Rc - reference counted sharing. Not thread-safe.
- Drops resource when last reference goes out of scope
- auto DeRef supports methods of referend
Examples:
let sp = Rc::new(String>::new("a string".to_string()));
let r1 = sp.clone();
let r2 = Rc::clone(&r1);
Arc - thread-safe reference counted sharing.
- Drops resource when last reference goes out of scope
- auto DeRef supports methods of referend
Examples:
let sp = Arc::new(String>::new("a string".to_string()));
let r1 = sp.clone();
let r2 = Arc::clone(&r1);
 
Ownership
Ownership Rules
- Enforce memory and data race safety
- Only one owner of any data item
- May have any number of non-mutable references
- May have only one mutable reference with no others
- Owner may not mutate when there are references being used
- References become inactive when they go out of scope
Examples:
let d = 3;
let mut mr = &d;
// let nmr = &d; // illegal
mr = 5; // d now holds 5
// d = 42; // illegal
 
Generics
Generic Functions - code generator for functions
- creates a new function for each distinct T
- T must satisfy specified trait constraints otherwise compile failure
Examples:
fn gf<_t:T>) {
  let tn = std::any::type_name::<T>();
  print!("\n t is type {:?}", tn);
}
Generic Structs - code generator for user-defined types
- creates a new Struct for each distinct T
- T must satisfy trait constraints otherwise compile failure
Examples:
#[derive(Debug)]
struct Point<T> { x:T, y:T, z:T }
  Next Prev Pages Sections About Keys