Hello Rustaceans,
I'm in need of some help understanding a case where two mutable references to a mutable variable are passed to two different functions, in main (the whole code is at the bottom):
const TEST_PATH: &str = "./mnist_test_data/mnist_test.csv";
let mut data_rdr_0 = data_reader(TEST_PATH);
let mut data_rcrds = data_records(&mut data_rdr_0);
let n_rows = data_number_rows(data_rcrds);
let n_cols = data_number_columns(&mut data_rdr_0);
;
I'm new to Rust and I come from Python, but it's my understanding that I can make any number of references I want to an immutable variable (&), but can only make one mutable reference to a mutable variable (&mut).
I searched for an explanation of why it was letting me pass &mut data_rdr_0
to the functions data_records
and data_number_columns
; meaning that the code is compiled.
I asked GPT-3 and its response was the following:
"In this code snippet, you are not actually making two mutable references to the same mutable variable. The data_reader()
function is returning a Reader instance which is owned by the data_rdr_0
variable. The data_records()
function is taking a mutable reference to that same Reader instance, while the data_number_columns()
function is also taking a mutable reference to the same Reader instance. This is allowed by Rust because the lifetimes of the two references are distinct. The first reference (to the Reader instance) will be valid until the data_records()
function returns, while the second reference (to the Reader instance) will be valid until the data_number_columns()
function returns."
If this is true, it is my understanding that the function data_records
returns at the line where it's assigned to the mutable variable data_rcrds
and thus, for the lines below this declaration, I would be allowed to make a new mutable reference, right?
It seems that way because I've done it on the last declaration in main. However, I cannot switch the last two declarations, let n_rows = ...
and let n_cols = ...
, as it tells me what I already knew:
- "cannot borrow
data_rdr_0
as mutable more than once at a time"
Can anyone tell me where my reasoning fails? It seems that the let n_rows = ...
declaration is the key behind my lack of understanding.
(For context, I'm trying to program a neural network using the MNIST data base. I did it in Python, but I want to do it in Rust for better perfomance.)
Thanks in advance!
Full code:
#![allow(unused)]
use csv::{Reader, StringRecordsIter, Error};
use std::fs::File;
fn data_reader(path: &str) -> Reader<File> {
return csv::Reader::from_path(path).unwrap();
}
fn data_records(reader: &mut Reader<File>) -> StringRecordsIter<File> {
return reader.records();
}
fn data_number_rows(records: StringRecordsIter<File>) -> usize {
return records.count();
}
fn data_number_columns(reader: &mut Reader<File>) -> usize {
return reader.headers().unwrap().len();
}
fn main() {
const TEST_PATH: &str = "./mnist_test_data/mnist_test.csv";
let mut data_rdr_0 = data_reader(TEST_PATH);
let mut data_rcrds = data_records(&mut data_rdr_0);
let n_rows = data_number_rows(data_rcrds);
let n_cols = data_number_columns(&mut data_rdr_0);
println!("{} by {}", n_rows, n_cols);
}