Reputation: 1010
When trying to run the following code:
fn main() {
let s1 = String::from("hello world");
println!("The first word in the string is: {}", return_first_word(&s1));
}
fn return_first_word(s: &String) -> String {
let t = s.split(" ");
String::from(t.next().unwrap())
}
I get the error cannot borrow as mutable
on the line String::from(t.next().unwrap())
. Naturally, when I replace the line let t = ...
with let mut t = ...
the code works perfectly.
My question is, can someone explain why? What is being borrowed here, and by what? I checked the type of my newly created immutable variable t
and it is an iterator. Why would it be an issue iterating over an iterator??
Upvotes: 4
Views: 1260
Reputation: 70257
If you're familiar with a language like Java, you might expect str::split
to return an array, but it actually doesn't. In Rust, str::split
returns an iterator. It doesn't actually split the entire string immediately; it gives you a special iterator object that does it as you iterate over the string.
Now, iteration is a stateful process in Rust. To iterate over something, you call Iterator::next
, which changes the iterator's internal state and produces the next value. If called repeatedly, it gives you every value of the iterator in order and then starts producing None
. Since next
changes the state of the iterator, it must have a mutable reference to the iterator.
When you declare a variable with let
in Rust, it's immutable. You can't change it. You've told the Rust system you have no intention of changing it. So Rust complains when you try to take a mutable reference to a thing (in your case, an iterator) that you promised to never change. Instead, you need to use let mut
to indicate your intentions.
Upvotes: 10