LGR Cheat Sheet
LGR Cheat Sheet
Table of Contents
Basic Types & Variables
Control Flow
References, Ownership, and Borrowing
Pattern Matching
Iterators
Error Handling
Combinators
Multiple error types
Iterating over errors
Generics, Traits, and Lifetimes
Functions, Function Pointers & Closures
Pointers
Smart pointers
Packages, Crates, and Modules
Unsigned integers
u8, u16, u32, u64, u128
Signed integers
i8, i16, i32, i64, i128
isize - Signed integer. Same number of bits as the platform's pointer type.
HashMap
use std::collections::HashMap;
// Instantiation
let user1 = User {
username: String::from("bogdan"),
active: true,
};
// Tuple struct
struct Color(i32, i32, i32);
let black = Color(0, 0, 0);
Enum
// Definition
enum Command {
Quit,
Move { x: i32, y: i32 },
Speak(String),
ChangeBGColor(i32, i32, i32),
}
// Instantiation
let msg1 = Command::Quit;
let LGR
msg2 = Cheat Sheet x: 1, y: 2 };
Command::Move{
let msg3 = Command::Speak("Hi".to_owned());
let msg4 = Command::ChangeBGColor(0, 0, 0);
Constant
const MAX_POINTS: u32 = 100_000;
Static variable
// Unlike constants static variables are
// stored in a dedicated memory location
// and can be mutated.
static MAJOR_VERSION: u32 = 1;
static mut COUNTER: u32 = 0;
Mutability
let mut x = 5;
x = 6;
Shadowing
let x = 5;
let x = x * 2;
Type alias
// `NanoSecond` is a new name for `u64`.
type NanoSecond = u64;
Control Flow
if and if let
let num = Some(22);
if num.is_some() {
println!("number is: {}", num.unwrap());
}
// match pattern and assign variable
if let Some(i) = num {
println!("number is: {}", i);
}
loop
let mut count = 0;
loop {
count += 1;
if count == 5 {
break; // Exit loop
}
} LGR Cheat Sheet
Nested loops & labels
'outer: loop {
'inner: loop {
// This breaks the inner loop
break;
// This breaks the outer loop
break 'outer;
}
}
Returning from loops
let mut counter = 0;
if counter == 10 {
break counter;
}
};
for loop
for n in 1..101 {
println!("{}", n);
}
match
let optional = Some(0);
match optional {
Some(i) => println!("{}", i),
None LGR Cheat Sheet
=> println!("No value.")
}
Borrowing rules
1. At any given time, you can have either one mutable reference or any number of immutable
references.
2. References must always be valid.
Creating references
let s1 = String::from("hello world!");
let s1_ref = &s1; // immutable reference
s2_ref.push_str(" world!");
let s2 = String::from("LGR");
let s3 = takes_and_gives_back(s2);
}
fn takes_copy(some_integer: i32) {
println!("{}", some_integer);
}
fn takes_ownership(some_string: String) {
println!("{}", some_string);
} // some_string goes out of scope and drop
is called. The backing memory is freed.
fn takes_and_gives_back(some_string: String)
-> String {
some_string
}
Pattern Matching
Basics
let x = 5;
match x {
// matching literals
1 => println!("one"),
// matching multiple patterns
2 | 3 => println!("two or three"),
// matching ranges
4..=9 => println!("within range"),
// matching named variables
x => println!("{}", x),
// default case (ignores value)
_ => println!("default Case")
} LGR Cheat Sheet
Destructuring
struct Point {
x: i32,
y: i32,
}
let p = Point { x: 0, y: 7 };
match p {
Point { x, y: 0 } => {
println!("{}" , x);
},
Point { x, y } => {
println!("{} {}" , x, y);
},
}
enum Shape {
Rectangle { width: i32, height: i32 },
Circle(i32),
}
match shape {
Shape::Rectangle { x, y } => //...
Shape::Circle(radius) => //...
}
Ignoring values
struct SemVer(i32, i32, i32);
match version {
SemVer(major, _, _) => {
println!("{}", major);
}
}
match numbers {
(first, .., last) => {
println!("{}, {}", first, last);
}
}
Match guards
LGR
let num Cheat Sheet
= Some(4);
match num {
Some(x) if x < 5 => println!("less than
five: {}", x),
Some(x) => println!("{}", x),
None => (),
}
@ bindings
struct User {
id: i32
}
match user {
User {
id: id_variable @ 3..=7,
} => println!("id: {}", id_variable),
User { id: 10..=12 } => {
println!("within range");
},
User { id } => println!("id: {}", id),
}
Iterators
Usage
// Methods that consume iterators
let v1 = vec![1, 2, 3];
let v1_iter = v1.iter();
let total: i32 = v1_iter.sum();
impl Counter {
fn new() -> Counter {
Counter { count: 0 }
} LGR Cheat Sheet
}
Error Handling
Throw unrecoverable error
panic!("Critical error! Exiting!");
Option enum
fn get_user_id(name: &str) -> Option<u32> {
if database.user_exists(name) {
return Some(database.get_id(name))
}
None
}
Result enum
fn get_user(id: u32) -> Result<User, Error> {
if is_logged_in_as(id) {
return Ok(get_user_object(id))
}
? operator
fn get_salary(db: Database, id: i32) ->
Option<u32> {
Some(db.get_user(id)?.get_job()?.salary)
}
Combinators
.map
let some_string = Some("LGR".to_owned());
.and_then
let vec = Some(vec![1, 2, 3]);
let first_element = vec.and_then(
|vec| vec.into_iter().next()
);
#[derive(Debug, Clone)]
struct CustomError;
Defining traits
trait Animal {
fn new(name: &'static str) -> Self;
fn noise(&self) -> &'static str { "" }
}
impl Dog {
fn fetch() { // ... }
}
Trait bounds
fn largest<T: PartialOrd + Copy>(list: &[T])
-> T {
let mut largest = list[0];
largest
}
impl trait
fn make_adder_function(y: i32) ->
impl Fn(i32) -> i32 {
let closure = move |x: i32| { x + y };
closure
}
Trait objects
pub struct Screen {
pub components: Vec<Box<dyn Draw>>,
}
Operator overloading
use std::ops::Add;
Static lifetimes
let s: &'static str = "Let’s Get Rusty!";
impl Point {
// Associated function
fn new(x: i32, y: i32) -> Point {
Point { x: x, y: y }
}
// Method
fn getX(&self) -> i32 { self.x }
}
Function pointers
fn do_twice(f: fn(i32) -> i32, arg: i32) ->
i32 {
f(arg) + f(arg)
}
Creating closures
let add_one = |num: u32| -> u32 {
num + 1
};
Returning closures
fn add_one() -> impl Fn(i32) -> i32 {
|x| x + 1
}
Closure traits
● FnOnce - consumes the variables it captures from its enclosing scope.
● FnMut - mutably borrows values from its enclosing scope.
● Fn - immutably borrows values from its enclosing scope.
Pointers
References
let mut num = 5;
let r1 = # // immutable reference
let r2 = &mut num; // mutable reference
Raw pointers
let mut num = 5;
// immutable raw pointer
let r1 = &num as *const i32;
// mutable raw pointer
let r2 = &mut num as *mut i32;
Smart pointers
Box<T> - for allocating values on the heap
let b = Box::new(5);
Rc<T> - multiple ownership with reference counting
let a LGR Cheat Sheet
= Rc::new(5);
let b = Rc::clone(&a);
Ref<T>, RefMut<T>, and RefCell<T> - enforce borrowing rules at runtime instead of compile time.
let num = 5;
let r1 = RefCell::new(5);
// Ref - immutable borrow
let r2 = r1.borrow();
// RefMut - mutable borrow
let r3 = r1.borrow_mut();
// RefMut - second mutable borrow
let r4 = r1.borrow_mut();
fn inner_private_function() {}
}
}
fn main() {
// absolute path
crate::outer_module::
inner_module::inner_public_function();
pub fn some_function() {
my_module::my_function();
}
// src/my_module.rs
pub fn my_function() {}