Rust

learn Rust programming language

Prerequisites

  • nodemon - enables compile and run on file change.

Development

# run on file(s) change (ensure `nodemon` is installed)
# turn off dead_code warning
nodemon --exec "RUSTFLAGS=\"$RUSTFLAGS -A dead_code\" cargo run" src/main.rs

# watch tests (run `cargo test` when any file changes)
cargo watch -x check -x test

# show output (e.g. `println!`)
cargo watch -x 'test -- --nocapture'

# to get a stack backtrace on panic
RUST_BACKTRACE=1 cargo run

Notes

  • compiles to LLVM IR
  • guarantees memory safety
  • no GC. compiler generates code at compile time to clean up of memory for variable that go out of scope, etc. no overhead at runtime for this. this is what makes it performant. zero-cost abstractions
  • excellent compiler messages
    • if you managed to appease the compiler, there’s a good chance your code will work–barring any logic flaws
  • out-of-bounds access at runtime causes the program to immediately stop
  • ownership rules apply across multiple threads
  • either one mutable reference (read/write) OR many immutable (read-only) references
  • no Null, only Option
  • traits are like interfaces in other languages
  • includes macros for metaprogramming
  • concurrency support via threads, channels, mutex
  • can call C code via extern
  • Lifetimes are, in some ways, Rust’s most distinctive feature
    • rust lifetimes are not in other languages. essentially tells the compiler when it can generate code to free memory/variables. the responsibility the runtime GC in other languages is shifted to you to take care of and think of (zero cost abstraction? not so much … there is the human cost). see Understanding lifetimes in Rust - LogRocket Blog for details.
  • cargo workspaces

Option and Result

see Option and Result | Learning Rust

Option

// An output can have either Some value or no value/ None.
enum Option<T> { // T is a generic and it can contain any type of value.
    Some(T),
    None,
}

Result

  • If a function can produce an error, we have to use a Result
  • used for all I/O, conversions, etc. anything that can fail.
// A result can represent either success/ Ok or failure/ Err.
enum Result<T, E> { // T and E are generics. T can contain any type of value, E can be any error.
    Ok(T),
    Err(E),
}

Smart Pointers (Box, Rc, Arc, Cell)

  • Box is for single ownership (single thread, stored on heap).
  • Rc is for multiple ownership (single thread, stored on heap).
  • Arc is for multiple ownership, but threadsafe (multi-thread, stored on heap).
  • Cell is for “interior mutability” for Copy types; that is, when you need to mutate something behind a &T.

Resources