просто наивный вопрос от новичка в Rust; как и следовало ожидать, это касается владения и изменчивости...
Проблема в следующем: у меня есть какая-то структура массива, которую я использую как прямоугольную матрицу.
struct Matrix {
lines: usize,
columns: usize,
content: Vec<f32>,
}
Внутри одномерный массив content
(с размером lines*columns
) представляет всю прямоугольную матрицу m
с m(i,j) = content[i*columns+j]
для любых заданных i
и j
.
Из этой матрицы я хотел бы извлечь строку. Но по разным причинам я также хотел бы сохранить размер этой строки, т.е. количество столбцов матрицы (и, в конечном итоге, некоторую дополнительную информацию в целом).
Для этого я использую новый тип Line
.
struct Line<'a> {
columns: usize,
content: &'a [f32],
}
Я предполагаю, что я использую срез для представления строки, так как это непрерывное пространство в памяти. Затем я могу реализовать функцию line()
как таковую:
impl Matrix {
fn line(&'a self, id: usize) -> Line<'a> {
let realindex = id * self.columns;
&self.content[realindex..realindex+self.columns]
}
}
Но есть проблема: поле content
в Line
неизменяемо. Я могу изменить содержимое Line
, надеясь, что это изменит содержимое матрицы владения.
В этом случае я думаю, что могу написать это, и это сработает:
struct Line<'a> {
columns: usize,
content: &'a mut [f32],
}
И я могу написать какую-нибудь line_mut
функцию для получения этой структуры:
impl Matrix {
fn line(&'a mut self, id: usize) -> Line<'a> {
let realindex = id * self.columns;
&mut self.content[realindex..realindex+self.columns]
}
}
Но что произойдет, если я хочу просто получить неизменяемую строку из матрицы? С первой версией Line
я не могу использовать line_mut
и получить изменяемую строку; и наоборот, со второй версией Line
я не могу использовать line
и получить неизменяемую строку...
Вопрос в следующем: я что-то упускаю или так оно и есть? Другими словами, есть ли способ заставить Rust делать вывод об изменчивости некоторых полей структуры в соответствии с требуемой изменчивостью при использовании структуры? Что-то вроде этого:
let a : Line = ...; // type of content = &[f32]
let mut b : Line = ...; // type of = &mut [f32]
Если это так, что было бы хорошим решением для обеспечения доступности обеих функций (изменяемой строки и неизменяемой строки)? Два разных типа (например, ImmutLine
и MutLine
)?
Я также видел RefCell
и внутреннюю изменчивость, но я не думаю, что это очень полезно в этом случае: во время компиляции я знаю, хочу ли я изменяемую или неизменяемую строку.
&T
или&mut T
— очень важное различие. Обычное соглашение для геттеров и т.п. состоит в том, чтобы иметь два отдельных метода и вспомогательных типа. Соблюдение соглашений об именах: два методаline(...)
/line_mut(...)
и два типаLine
/LineMut
. - person E_net4 the curator   schedule 26.04.2019