DEV Community

Cover image for 30 Days of Rust - Day 7
johnnylarner
johnnylarner

Posted on • Edited on

30 Days of Rust - Day 7

After a week of learning, I'm going to dedicate this blog article to reflecting on what we've learned so far. Before that though here are a few fun facts:

  1. The blog series has had over 300 views so far - so THANKS for that :)
  2. If you've read every article in the series, that's over 4500 words.
  3. Together we've asked and answered 30 questions about Rust.

To break from tradition, I won't be asking any questions today. Tomorrow I'll sketch out what I'm planning for the next week of the series 💪

Yesterday's questions answered

  • All values are by default stack-allocated in Rust. Box is a way to tell the compiler to put a value on the heap. This makes a Box a smart pointer. Values should be added to the heap when they are expected to grow or be shared of multiple threads.
  • An Arc is a smart pointer that manages multiple atomic references to a value on a heap. In using an Arc, a developer can guarantee thread safety for access to a value. To manipulate values references by an Arc, you need to first wrap the value in a Mutex before wrapping it in an Arc.
  • A Mutex guarantees single-thread access to a value using the .lock method. This enables threads to update values at a given reference safely.
  • Having scanned the Rust book, I couldn't find a high-level API for thread management. I did learn about the channel concept which enables threads to pass messages to one another.
  • The where clause is used to improve bounding for traits during generic declarations. The documentation is lacking here and I think it's probably okay to drop this topic for now.
  • I couldn't find other exciting features for a closure. But I learned that Rust's compiler will type a closure depending on whether it uses variables referenced in another scope.

7 Days of Rust in 45 seconds

Project management

Depend on Rust's package manager cargo:

cargo new <project_name> # Project init
cargo build; cargo compile; cargo run; # Build and run stuff
cargo add <library> # Add dependencies
cargo test # Run your tests
Enter fullscreen mode Exit fullscreen mode

Im- / export your Rust

Declare crates consisting of mods inside of a public function to make code exportable:

pub fn my_crate() {
    crate::module_root::to::module()
}
Enter fullscreen mode Exit fullscreen mode

The same :: colon syntax is used to import crates and their submodules. You can import wildcards, a single or multiple module members.

Indeed I do declare

  • let and const for variable and constants.
  • mut follows let if you want to make something mutable.

Control the flow

  • Rust supports if/else statements as well as match statements.
  • Tend towards match over if as match is used in several Rust patterns.
  • You can loop with loop, for and while. Opt for loop if you need to use uninitialised variables or want a returned value from break.
  • Use .iter method on collections when iterating to get references to its values.

The important data types

  • Use arrays and tuples for fixed size collections of single and mixed types, respectively.
  • Use Vec for a growable collection.
  • Favour String over read-only &str
  • HashMaps for single-typed lookups, structs for logical data groups, enum for categories
  • Use traits to define interfaces for structs

DaFunc?

  • Declare functions with fn
  • Functions are scoped and will shadow variables outside of their scope
  • Omit return and trailing ; to do an implicit return
  • Anonymous functions are declared using two pipe operators and are called a closure
  • closures can access variables declared at the same level as them inside their body. Use them for threading!

Pointing out the not obvious

  • Static values are stored on the stack, dynamic, unknown or recursive structures are stored on the heap.
  • Each value on the heap in Rust can only have one owner, thus reassigning a variable to a new variable will relinquish the latter of its ownership.
  • Each value has a scope and it will be dropped once that scope is exited -> do you miss the garbage collector?
  • Access values via the & operator

Catching your errors

  • If a function doesn't have a Result return type, chain its call with .expect to catch panic.
  • Otherwise you can use a match statement to handle the error.
  • Errors are actually referred to as a panic :D

Stuff I barely understood

  • Use the Box API to allocate a value to the heap
  • Spawn threads with thread::spawn and join all threads with .join
  • Use Arc to ensure thread-safe resource access

Top comments (0)

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay