Lesson 7 of 20
References and Borrowing
References and Borrowing
Instead of transferring ownership, you can borrow a value by taking a reference to it.
Immutable References
&T is a reference to T. You can have as many immutable references as you like:
fn calculate_length(s: &String) -> usize {
s.len()
} // s is a reference — nothing is dropped here
let s = String::from("hello");
let len = calculate_length(&s); // borrow s
println!("{} has {} letters", s, len); // s still valid
Mutable References
&mut T allows modifying the borrowed value, but with a restriction: you can have at most one mutable reference to a value in a given scope:
fn change(s: &mut String) {
s.push_str(", world");
}
let mut s = String::from("hello");
change(&mut s);
The Borrowing Rules
- At any given time, you can have either one mutable reference or any number of immutable references — never both.
- References must always be valid (no dangling pointers).
These rules prevent data races at compile time — not at runtime.
Slices as References
&[T] is an immutable slice — a reference to a contiguous sequence of T:
fn first_element(slice: &[i32]) -> i32 {
slice[0]
}
Your Task
Implement four functions using references (no ownership transfer):
sum_slice(numbers: &[i32]) -> i32— sum all elements.largest_in_slice(numbers: &[i32]) -> i32— return the largest element.double_all(numbers: &mut Vec<i32>)— double every element in-place.count_positive(numbers: &[i32]) -> usize— count elements greater than zero.
Rust (Miri) loading...
Loading...
Click "Run" to execute your code.