在学习 Rust 中的迭代器时,我创建了以下结构来隐藏二维集合的实现:
use std::slice::{Items, MutItems};
use std::vec::{Vec};
pub struct Table<T> {
pub width: uint,
pub height: uint,
data: Vec<T>
}
impl<T: Clone> Table<T> {
pub fn from_elem(width: uint, height: uint, value: T) -> Table<T> {
Table {
width: width,
height: height,
data: Vec::from_elem(width * height, value)
}
}
}
impl<T> Table<T> {
pub fn get_row_column(&self, index: uint) -> (uint, uint) {
(index / self.width, index % self.width)
}
pub fn iter<'a>(&'a self) -> Items<'a, T> {
self.data.iter()
}
pub fn iter_mut<'a>(&'a mut self) -> MutItems<'a, T> {
self.data.iter_mut()
}
}
iter
and方法的目标iter_mut
是,该结构的用户无需担心数据是以行优先还是列优先格式存储的;迭代器将简单地以最有效的顺序提供元素。
但是,在使用这种数据结构时,我经常需要知道特定的行和列才能获取一些外部数据:
fn get_input(row: uint, column: uint) -> uint {
row * 10 + column / 2
}
fn main() {
let mut table = Table::from_elem(640, 480, 0u);
for (index, value) in table.iter_mut().enumerate() {
let (row, column) = table.get_row_column(index);
*value = get_input(row, column);
}
}
但是,一旦我尝试调用该get_row_column
方法,就会收到以下编译器错误:
main.rs:56:33: 56:38 error: cannot borrow `table` as immutable because it is also borrowed as mutable
main.rs:56 let (row, column) = table.get_row_column(index);
^~~~~
main.rs:55:31: 55:36 note: previous borrow of `table` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `table` until the borrow ends
main.rs:55 for (index, value) in table.iter_mut().enumerate() {
^~~~~
main.rs:59:6: 59:6 note: previous borrow ends here
main.rs:55 for (index, value) in table.iter_mut().enumerate() {
main.rs:56 let (row, column) = table.get_row_column(index);
main.rs:57 *value = get_input(row, column);
main.rs:58 }
main.rs:59 }
^
完成我在这里尝试做的事情的正确方法是什么? 我可以添加一个set
采用行号和列号并显式循环行和列索引的方法,但是用户必须担心行优先与列优先排序:
impl<T> Table<T> {
fn get_index(&self, row: uint, column: uint) -> uint {
row * self.width + column
}
pub fn set(&mut self, row: uint, column: uint, value: T) {
let index = self.get_index(row, column);
self.data[index] = value;
}
}
fn main() {
let mut table = Table::from_elem(640, 480, 0u);
for row in range(0, table.height) {
for column in range(0, table.width) {
table.set(row, column, get_input(row, column));
}
}
}
是否有一种约定或最佳实践来改变结构的内部成员,同时仍然允许访问不可变的成员和方法?或者这是否完全违反了安全保证?