30 days of Rust - Day 4

johnnylarner

johnnylarner

Posted on April 26, 2023

30 days of Rust - Day 4

Dear diary,
Don't blame me for breaking the 6 am rule today - sleep is great at improving your memory. I can remember heaps of stuff about Rust. How much exactly I can't tell you, as me later at runtime.

Yesterday's questions answered

  • Yes, it's possible to do this once a match has been made. A function could be used to evaluate a second criteria. I can't think of a good example, but this code compiles:
match n {
    1 if is_greater_than_zero(n) => println!("{} is greater than zero", n),
    0 if is_greater_than_zero(n) => println!("{} is greater than zero", n),
    -1 if is_greater_than_zero(n) => println!("{} is greater than zero", n),
_ => println!("{} unknown number", n),
}
Enter fullscreen mode Exit fullscreen mode
  • Some is a way of evaluating that an Option type is non-null. Typically, retrieving items from collections yields an Option.
  • return is best used to indicate an early exit from a function (in an if block, for example). But in essence it's a matter of taste/readability. Opinions here.
  • impl isn't doing anything fancy, it's the Rust way of declaring methods for a struct or enum.

Today's open questions

  • What is an Option type? (Already answered: An enum that represents the existence (Some) or non-existence (None) of a variable's value.
  • Not really a question but: I was introduced to ownership in the context of scope today, how can I concisely describe this concept?
  • Random one: how can I write a unit test in Rust?
  • How do I access something on the stack in Rust?
  • Why can primitives be reassigned without renouncing ownership?
  • Can anything other than a struct implement a trait?
  • What's the difference between an impl and trait, is impl bound to a single struct?

Memories

As the desperate puns at the top suggest, I was introduced to some basics about CS memory management as they relate to Rust.

Stack it

stack it

Anything thing that Rust wants to add to your machine's stack must have a fixed size at compile time. Classic examples of this would be function, struct, trait or impl.

Rules of the heap

kinf of the heap

Your machine's heap contains memory representations of a structure's runtime value. When you add something to the heap, you receive a pointer to its location. Hence why we often access values on the heap using the & operator.

Rust implements rules around the heap to provide an opinionated way of managing variables, which also introduces the concept of ownership.

  1. Each value has a variable that's called its owner
  2. There is only one owner at a time
  3. When the owner goes out of scope the value disappears

Don't trust your variables (if they ain't primitive)

Whenever you reassign a variable to a new variable, you relieve the former variable of its ownership of the value it points to. If you want to prevent this behaviour, you can call the clone method on the value. This only works, however, for non-primative types. Why is that??

This is very different from Python:

my_dict = {"Hello": "World"}
my_final_dict = my_other_dict = my_dict # Valid code by gross!
print(my_final_dict, my_other_dict, my_dict) # No error
Enter fullscreen mode Exit fullscreen mode

More data types

Hash maps

Not much to say here. Hash maps must have keys and values of the same types, respectively. They have some useful but verbose methods such as contains_key. You can count the number of keys using the len method and retrieve a key using get. get will return you an Option which will be either Some or None.

Structs

Anyone familiar with JavaScript's object or Go's struct will know what's up here. Basically, we declare a struct with a number of arbitrarily typed fields. These fields are comma deliniated and wrapped in curly braces.

Traits

Finally something ::new()! I learned some basics about trait types today. A trait can be used in a similar fashion to an interface in Go and Java or like a Protocol in Python. Combining a trait with a struct offers a conceptually convenient way to separate data structures from behaviour. Traits also introduced me to the Self return type and the &self argument.

Different to Go (I think) and Python's Protocol, a trait must be explicitly impl (slightly less verbosely than Java) for a given struct.

That's it for today -> see you tomorrow.

💖 💪 🙅 🚩
johnnylarner
johnnylarner

Posted on April 26, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related