code for article pfeilbr/rust-playground
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
, onlyOption
- 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
- The Rust Programming Language book
- Rust by Example
- Table of Contents - Rust Cookbook
- rust-analyzer - Bringing a great IDE experience to the Rust programming language.
- GitHub - watchexec/cargo-watch: Watches over your Cargo project's source.
- Rust: A Language for the Next 40 Years - Carol Nichols
- A collection of notable Rust blog posts
- Understanding lifetimes in Rust - LogRocket Blog
- The Little Book of Rust Macros
- Yoututbe | Jon Gjengset - rust videos
- dtolnay/cargo-expand: Subcommand to show result of macro expansion
- Wrapper Types in Rust: Choosing Your Guarantees
Twitter • Reddit