Reputation: 4582
I wanted to input a value and assign it to a variable that is immutable (should be). How can I do that?
Currently, I am doing this:
use std::io;
fn main() {
let mut a = 0;
let mut b = 1;
let mut nth_term = String::new();
io::stdin().read_line(&mut nth_term);
}
But without &mut
, it generates an error: types differ in mutability
. If I remove mut
from the declaration I get an error like this:
error[E0308]: mismatched types
--> src/main.rs:5:27
|
5 | io::stdin().read_line(&nth_term).expect("I/O error");
| ^^^^^^^^^ types differ in mutability
|
= note: expected mutable reference `&mut std::string::String`
found reference `&std::string::String`
How can I have something like this:
let input_var = input(); // or some other function that inputs the value and directly assigns it.
I tried reading the official documentation, the first few chapters, but in vain.
Upvotes: 2
Views: 621
Reputation: 27915
Mutability in Rust follows the name, not the value. So if you have a value that is bound to a mutable variable, and you want it to be immutable, all you have to do is rebind it:
fn main() {
let mut nth_term = String::new();
io::stdin().read_line(&mut nth_term).expect("I/O error");
let nth_term = nth_term;
// ^^^^^^^^-- no `mut`
}
Rebinding a value to the same name with a different mutability is common (see What does 'let x = x' do in Rust?).
You can also put the original binding in a block expression to minimize the scope of the mut
variable:
fn main() {
let nth_term = {
let mut nth_term = String::new();
io::stdin().read_line(&mut nth_term).expect("I/O error");
nth_term
};
}
BufRead::read_line
is defined this way so that you don't need to allocate a new String
for each new line read. The method has to take &mut
because it can grow the string. Although you can iterate over input lines with stdin().lines()
, which does yield owned String
s, there is no standard I/O function that reads a single line from stdin and returns a String
(which you could simply bind to a non-mut
variable). Of course, if you find yourself doing that a lot, you could just write your own function that contains the mut
and returns, for instance, an io::Result<String>
.
Upvotes: 4