-
-
Save naironics/b51a1754de875012788e62b456cc5749 to your computer and use it in GitHub Desktop.
Rust concept explanations
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| My explanation of the main concepts in Rust | |
| =========================================== | |
| There are three main concepts with Rust: | |
| 1. Ownership (only one variable "owns" the data at one time, and the owner is in charge of deallocating) | |
| 2. Borrowing (you can borrow a reference to an owned variable) | |
| 3. Lifetimes (all data keeps track of when it will be destroyed) | |
| These are fairly simple concepts, but they are often counter-intuitive to concepts in other languages, so I wanted to give a shot at | |
| explaining these concepts in more detail. Because C++ is also starting to adopt them, there is definitely a huge benefit to learning | |
| these concepts | |
| ## Ownership | |
| When you own an item in real life, you are usually the sole owner of the item. When you know longer want an item you can either give it to another person | |
| or destroy it. | |
| Rust does something very similar. When you declare a variable in Rust, the variable "owns" the data. | |
| ```rust | |
| let a = 2; // a "owns" 2 | |
| ``` | |
| When a variable owns something it can give it to other variables using assignment. | |
| After giving away your data, the old variable cannot access the value anymore, and the new variable is the new owner. | |
| ```rust | |
| let a = 2; // a "owns" 2 | |
| let b = a; // a gives its data to b | |
| println!("{}", b); // b now owns the data previously in a | |
| println!("{}", a); // ERROR: a no longer has anything | |
| ``` | |
| At the end of the scope where the owner is created, the data is destroyed | |
| ```rust | |
| { | |
| let a = Box::new(2); // a owns a heap allocated integer | |
| } // a's data deallocated here | |
| ``` | |
| Tips & Tricks: | |
| * Passing values into functions will "move" the data into the function variable. Once that happens the original variable | |
| cannot be accessed. This seems pretty restrictive, which is why the next topic tries to solve this. | |
| ```rust | |
| fn hello(a: Box<i32>) { | |
| println("{:?}", a); // prints "2" | |
| } | |
| fn main() { | |
| let b = Box::new(2); | |
| hello(b); // moves b into hello's a parameter | |
| b; // ERROR: cannot access b after it gave its value to a | |
| } | |
| ``` | |
| * It is easy to forget ownership concepts when working with more complex data | |
| ## Borrowing | |
| Even though you are the only person who owns an item you often don't want to do everything yourself. | |
| In the same sense, you might want to pass a value to a function without moving the value inside the function. | |
| Rust allows you to do this using the concept of borrowing. Borrowing is just like what you think it is, it just allows | |
| another variable to temporarily borrow the data in your variable and gives it back when its done. | |
| For example, if you own a computer but don't know how to install a software package, you might temporarily give the computer to a friend who knows so that he can install it for you. | |
| So what happens with borrowing is that: | |
| 1. You give the item to your friend (but you still own it) | |
| 2. Your friend does stuff with the borrowed item | |
| 3. Your friend gives back the item to you | |
| Rust allows you to have two types of borrows: | |
| * immutable borrows with '&' (I want to borrow your book but I promise not to scribble on it) | |
| To access the value in a reference you use the dereference operator '*'. | |
| When you borrow a variable, that variable becomes inaccessable until the borrowed variable | |
| is destroyed. | |
| ```rust | |
| let mut x = 5; | |
| let y = &mut x; // y says 'hey can I borrow your data' to x | |
| println!("{}", x); // ERROR: x no longer has the data, y has it! | |
| ``` | |
| When a borrowed variable is destroyed, it gives back the borrowed value back to the owner. | |
| ```rust | |
| let mut x = 5; | |
| { | |
| let y = &mut x; // y says 'hey can I borrow your data' to x | |
| *y += 1; // y changes the borrowed data | |
| } // y gives back the data to x | |
| println!("{}", x); // x has the data back again (and its changed to 6) | |
| ``` | |
| Rust also has some extra rules for borrowing. | |
| You can have either one of these or the other in the current scope, but not both: | |
| * You can have lots of read-only borrows to a variable | |
| * You can have one read-write borrow to a variable | |
| Tips & Tricks: | |
| * Function parameters end up mostly being borrowed references because otherwise the value will be moved inside the function | |
| * Function return values should not be references to local variables and Rust will not let you do this. | |
| If you returned a pointer to a local value in C you could either end up with corrupted data or the return value won't know when to deallocate its data | |
| which is bad either way you look at it | |
| * Don't worry about dereferencing to "read" or "write" (depending on & or &mut) the value of a borrowed reference | |
| ```rust | |
| enum State { | |
| Hello, | |
| Bye, | |
| } | |
| fn hello(blah: &State, foo: &mut i32) { | |
| match *blah { // you are only reading an immutable reference so its fine | |
| State::Hello => println!("Hello!"), | |
| State::Bye => println!("Bye!"), | |
| } | |
| *foo += 1; // you are only writing to a mutable reference so its fine | |
| } | |
| ``` | |
| * Do worry about assigning dereferenced references to variables, because that will instead try to move the data to the new variable | |
| ```rust | |
| enum State { | |
| Hello, | |
| Bye, | |
| } | |
| fn hello(blah: &State) { | |
| let thief = *blah; // ERROR: blah can't give a borrowed item to thief! | |
| // thief is going to take the value without giving it back to the original owner | |
| } | |
| ``` | |
| ## Lifetimes | |
| TODO: write this later |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment