Rust Log 🦀
i caved
May 23rd:
- Rust is a very opinionated programming language! As a newbie, I feel like I need to understand the Rust philosophy of approaching memory without garbage collector/fighting borrow checker in order to actually get it. To me, Rust philosophy is like: “worry about this now, compile time will be slow” but “runtime will be super fast”.
- Box::new(5), pointer that allocates memory on the heap for an integer, 5.
- Detail in error messages matches the error complexity! Rust compiler is nice (e.g. if you use a variable that has been moved).
fn main() {
let x = Box::new(5);
let mut y = x; // mutable reference to x.
*y = 4;
assert_eq!(*y, 4);
println!("Success!");
}
Compiling playground v0.0.1 (/playground)
error[E0382]: borrow of moved value: `x`
--> src/main.rs:9:5
|
3 | let x = Box::new(5);
| - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
4 |
5 | let mut y = x; // mutable reference to x.
| - value moved here
...
9 | assert_eq!(*x, 4);
| ^^^^^^^^^^^^^^^^^ value borrowed here after move
|
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider cloning the value if the performance cost is acceptable
|
5 | let mut y = x.clone(); // mutable reference to x.
| ++++++++
For more information about this error, try `rustc --explain E0382`.
error: could not compile `playground` (bin "playground") due to 1 previous error
- string literals (&s aka string slice) vs. String types (String::from("hello world") using a string literal, stored as vector of bytes) are a thing!
- .tostring() converts a string literal to a String type
- &mut vs ref: &mut is used to create a mutable reference while ref is used to create a reference in destructuring (for example, a tuple)
fn main() {
let t = (String::from("hello"), String::from("world"));
// Using ref to borrow the elements of the tuple
let (ref s1, ref s2) = t;
// Now s1 and s2 are references to the elements of t
println!("{}, {}", s1, s2); // Output: "hello", "world"
- You can only borrow once (cannot create multiple mutable references for the same variable. You can create mutliple immutable references, however. This is denoted by &s. This is an example of creating multiple mutable references, and is wrong:
fn main() {
let mut s = String::from("hello");
let r1 = &mut s;
let r2 = &mut s;
println!("{}, {}", r1, r2);
println!("Success!");
}
Why does Rust only allow one copy of mutable references at a time? Data race will occur if not. A data race is when two or more threads access the same memory location concurrently. Multiple versions for the same reference. Rust core philosophy: multiple threads can read the data (immutable references) or only one thread can modify the data at any time (single mutable reference).
You are allowed to borrow a mutable object as an immutable one.
fn main() {
let mut s = String::from("hello, ");
borrow_object(&s);
s.push_str("world");
println!("Success!");
}
fn borrow_object(s: &String) {}
May 25th
Modules and crates today.
- Modules allow for limited scope, avoid naming conflicts. Group related code.
- src/main.rs = crate root for binary crate
- src/lib.rs = crate root for library crate
- you need to preface with use crate::sibling_module if you have sibling modules (modules at the same level) and need to access the sibling_module
-
If you have a root crate with submodules, at the root file, you need to declare your submodules at the top Example: front_of_house – hosting.rs – mod.rs – serving.rs
mod.rs would have:
pub mod hosting; pub mod serving;```rust mod front_of_house { mod hosting { fn add_to_waitlist() {} } }
pub fn eat_at_restaurant() { // Absolute path crate::front_of_house::hosting::add_to_waitlist();
// Relative path
front_of_house::hosting::add_to_waitlist(); } ```
- add_to_waitlist is defined in the same root crate as eat_at_restaurant so you can use the “crate” word to specify the same root crate
More examples: Correct:
pub mod foo {
pub mod bar {
pub fn b() { println!("b"); }
}
pub fn a() { bar::b(); }
}
fn main() {
foo::a();
}
it is valid to use bar::b() just to refer to b() because “bar” and “b” are both public. You can refer to functions in the same module to refer to the items in submodules.