I am currently learning Rust for fun. I have some experience in C / C++ and other experience in other programming languages that use more complex paradigms like generics.
Background
For my first project (after the tutorial), I wanted to create a N-Dimensional array (or Matrix) data structure to practice development in Rust.
Here is what I have so far for my Matrix struct and a basic fill and new initializations.
Forgive the absent bound checking and parameter testing
pub struct Matrix<'a, T> {
data: Vec<Option<T>>,
dimensions: &'a [usize],
}
impl<'a, T: Clone> Matrix<'a, T> {
pub fn fill(dimensions: &'a [usize], fill: T) -> Matrix<'a, T> {
let mut total = if dimensions.len() > 0 { 1 } else { 0 };
for dim in dimensions.iter() {
total *= dim;
}
Matrix {
data: vec![Some(fill); total],
dimensions: dimensions,
}
}
pub fn new(dimensions: &'a [usize]) -> Matrix<'a, T> {
...
Matrix {
data: vec![None; total],
dimensions: dimensions,
}
}
}
I wanted the ability to create an "empty" N-Dimensional array using the New fn. I thought using the Option enum would be the best way to accomplish this, as I can fill the N-Dimensional with None
and it would allocate space for this T generic automatically.
So then it comes down to being able to set the entries for this. I found the IndexMut
and Index
traits that looked like I could do something like m[&[2, 3]] = 23
. Since the logic is similar to each other here is the IndexMut
impl for Matrix
.
impl<'a, T> ops::IndexMut<&[usize]> for Matrix<'a, T> {
fn index_mut(&mut self, indices: &[usize]) -> &mut Self::Output {
match self.data[get_matrix_index(self.dimensions, indices)].as_mut() {
Some(x) => x,
None => {
NOT SURE WHAT TO DO HERE.
}
}
}
}
Ideally what would happen is that the value (if there) would be changed i.e.
let mut mat = Matrix::fill(&[4, 4], 0)
mat[&[2, 3]] = 23
This would set the value from 0 to 23 (which the above fn does via returning &mut x
from Some(x)
). But I also want None
to set the value i.e.
let mut mat = Matrix::new(&[4, 4])
mat[&[2, 3]] = 23
Question
Finally, is there a way to make m[&[2,3]] = 23
possible with what the Vec struct requires to allocate the memory? If not what should I change and how can I still have an array with "empty" spots. Open to any suggestions as I am trying to learn. :)
Final Thoughts
Through my research, the Vec struct impls I see that the type T
is typed and has to be Sized. This could be useful as to allocate the Vec with the appropriate size via vec![pointer of T that is null but of size of T; total]
. But I am unsure of how to do this.
Index
trait? What do you return if the value at that index doesn't exist? – kmdrekoIndexMut
as desired is possible, but sinceIndexMut
's output type must match a correspondingIndex
trait, it would have troubling implications for theIndex
implementation. – kmdrekoIndex
trait I have the same problem if the value of theOption<T>
enum isNone
. I don't know what to return. Currently I just have it panic but I am unsure of what to do that is idiomatic to Rust and has the functionality to return a "null" pointer or something that makes sense to the user. – IpFruionprintln!("{}", m[&[1, 1]]);
wherem[&[1, 1]]
is the option enumNone
it would error out because it would be doing a to_string on a "null" value or something similar. But for functionality itIndex
should return the value that is at that spot in the matrix. – IpFruion