Hi All! Welcome to the Reading Club for Rust’s “The Book” (“The Rust Programming Language”). This is week 1 (the beginning!!).

Have a shot at going through “the reading” and post any thoughts, confusions or insights here

“The Reading”

The Twitch Stream

What’s Next Week?

  • Chapters 3 and 4
  • Start thinking about challenges or puzzles to try as we go in order to get some applied practice!
    • EG, Advent of Code
    • Maybe some basic/toy web apps such as a “todo”
  • Jayjader@jlai.luM
    link
    fedilink
    English
    arrow-up
    1
    ·
    4 months ago

    This will make more sense once we (this community) get to the 4th week/session and properly get into ownership, but lemme try to explain anyways:

    A variable without a & in front is moved into the [function’s] scope.

    Upon exiting a scope, Rust automatically drops/de-allocates any variables that were owned by/moved into said scope.

    This is why you need to either

    1. pass by ref / have the scope borrow a reference to the variable, or

    2. have your function return the variable/object/memory handle that was moved into it

    when you want a variable/some data to “out-live” being passed as argument to a function call.

    Most often you will use 1), but there are some cases where it can be much nicer to move things “into” a function call and store what you “get back out” (i.e. the return value). Using a “[Type-]State” pattern/approach is a good example of such a case (here’s a better explanation than I can give in a lemmy comment).

    Example:

    struct Unauthenticated;
    struct Authenticated { name: String };
    
    impl Unauthenticated {
        fn login(self, username: String) -> Authenticated {
            Authenticated { name: username }
        }
    }
    
    pub fn main() {
        let un_authed_user = Unauthenticated::new();
        let authed_user = un_authed_user.login("Alice"); // `un_authed_user` has effectively been moved into `authed_user`
    }
    

    Here, we as programmers don’t need to worry about making sure un_authed_user gets cleaned up before the program exits, and we don’t need to worry about data that could have been stored inside un_authed_user being freed too early (and thus not being available to authed_user).

    Admittedly, this is a contrived example that doesn’t really need to worry about ownership, it’s just the bare minimum to illustrate the idea of moving data into and then back out of a function scope. I don’t know of a small enough “real-world” example to give here instead.

    • freamon
      link
      fedilink
      English
      arrow-up
      2
      ·
      4 months ago

      Thank you.

      I think there’s more to it though, in that simple values aren’t moved, they’re always copied (with any & in front indicating whether it’s the value to copy or the address)

      To illustrate:

      fn how_many(a: u32, fruit: String) {
          println!("there are {} {}", a, fruit);
      }
      
      
      fn main() {
          let a=4;
          let fruit = String::from("Apples");
          how_many(a, fruit);
      
          println!("the amount was {}", a);         // this works
          println!("the fruit was {}", fruit);      // this fails
      }
      
      

      The ‘a’ was copied, and the ‘fruit’ was moved.

      • Jayjader@jlai.luM
        link
        fedilink
        English
        arrow-up
        2
        ·
        4 months ago

        Correct! Values that can be copied are copied, and those that aren’t are moved.

        All primitive data types are copyable (or "are Copy ", which will make more sense once we get to Traits). I think arrays of primitives are as well? Most everything else isn’t by default.

        One of my favorite parts of Rust is that to make something copyable, you “just” implement the Copy trait for that thing.