Every time I start trying out something new in rust, I run into compiler errors complaining to me about things like mis-matched types, ‘cannot borrow variable’, etc. I go back to the chapters about “ownership” and “borrowing” (found in the rust book), read a little bit, then feel foolhardy enough to take another stab at it.

I feel like this is something foundational about the language and since I don’t yet have a full understanding of it, any other part that I try to hack away at will be fraught with compiler errors. I’m not sure what I am missing.

To work this out better in my head, I’ll try imagining that I’m at a library looking for a book to borrow. There are three libraries accessible to me. One of them has the book “A Storm of Swords” that I want to read.

let library_in_queens: Vec<&str> = vec!["Metaprogramming Ruby", "Ancillary Justice", "The Great Gatsby"];
let library_in_manhattan: Vec<&str> = vec!["SICP", "The Little Schemer", "Linear Algebra"];
let library_in_bronx: Vec<&str> = vec!["A Storm of Swords", "The Silmarrion"];

I have a function called library_has_book which takes a vector (of book titles), the book that I want, and, after iterating through the collection, returns a boolean value.

fn library_has_book(library: Vec<&str>, title: &str) -> bool {
    for book in library {
        if book == title {
            return true
        }
    }

    false
}
let book = "A Storm of Swords".to_string(); // still not sure why I have to do this.

if library_has_book(library_in_queens, book) {
    // borrow the book
}

// Compiles. No problems.

if library_has_book(library_in_manhattan, book) {
    // error: use of moved value: `book`
}

After using the book variable binding, I couldn’t use the binding itself again anywhere else. That seems like a maddening thing to keep track of but apparently I’ve been using a solution already - just not in the right place.

in library_has_book, the arguments contain ampersands (&). I’m not sure how strings are handled yet, as I see &str used quite a bit, but the Vec<&str> clued me in to what’s going on. The ampersands represent references to the bindings that you pass in, and not the value itself. When the code gets executed, rust takes the references provided and goes to their location in memory, and then pulls the data from there while keeping the original binding intact.

if library_has_book(library_in_queens, &book) {
  // `book` keeps it's original meaning and place, and only provides a reference to it
}

Now book can be used as much as needed, so long as the references are being made to it.