Let's take a look at some code that includes a function that takes in a string and returns the length, then, after that function, prints out both the contents of the string and the length:
main.rs
fn main() {
let s1 = String::from("hello");
let (s1, len) = calculate_length(s1);
println!("The length of '{}' is {}.", s1, len);
}
fn calculate_length(s: String) -> (String, usize) { // s is a String
(s.clone(), s.len())
} // Here, s goes out of scope and `drop` is called
That is... sorta gnarly. We could potentially copy s1 into calculate_length instead of returning a tuple, but either way... not great! Luckily, Rust does not actually require us to do this. With Rust, you can pass a value as a reference, which enables the function or variable to get the contents without taking ownership. You do this by putting an ampersand (&) in front of both the type and the variable when it's passed, like so:
main.rs
fn main() {
let s1 = String::from("hello");
let len = calculate_length(&s1);
println!("The length of '{}' is {}.", s1, len);
}
fn calculate_length(s: &String) -> usize { // s is a reference to a String
s.len()
} // Here, s goes out of scope. But because it does not have ownership
// of what it refers to, nothing happens.
The two big changes here are calculate_length(&s1) and calculate_length(s: &String). By default, if something is a reference, it is immutable. You can make a reference mutable by using &mut instead of &. Here's an example:
main.rs
fn main() {
let mut s = String::from("hello");
change(&mut s);
}
fn change(some_string: &mut String) {
some_string.push_str(", world");
}
main.rs
use std::collections::HashMap;
fn main() {
let mut scores = HashMap::new();
scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
get_score(&scores, String::from("Red"));
get_score(&scores, String::from("Blue"));
}
fn get_score(scores: &HashMap<String, i64>, team_name: String) {
let score = match scores.get(&team_name) {
Some(num) => num.to_string(),
None => "nonexistent".to_string()
};
println!("{}'s score is {}", team_name, score);
}
In summary, here are the rules for references:
At any given time, you can have either but not both of: