Consider alternative syntax for slicing (Index and IndexMut)?
alexpyattaev opened this issue · comments
Compared to Python, ndarray crate has an obvious difference in slicing. Arguably, this is the most annoying part of ndarray library. It would be nice to be able to do something like the following:
let a = SomeMatrix::default();
let y = &a[1]);
let x = &a[1..3]
let z= &a[[1..3, 4..3]]);
Now with ndarray, this code would look quite nasty, but it does not have to. Rust does allow the Index operator (i.e., [])to be "overloaded" depending on the type of whatever is being used as "indexer", as in the example below:
#[derive(Default)]
struct ArrayBase{
data:[u32;5]
}
impl std::ops::Index<std::ops::Range<usize>> for ArrayBase
{
fn index(&self, index: std::ops::Range<usize>) -> &Self::Output{
&self.data[index]
}
type Output = [u32];
}
impl std::ops::Index<usize> for ArrayBase
{
fn index(& self, index: usize) -> &Self::Output{
&self.data[index]
}
type Output = u32;
}
Using this, one could have the nice syntax actually work. Obviously, this extends to higher dimensions too:
impl <const D:usize> std::ops::Index<[std::ops::Range<usize>;D]> for ArrayBase<D>
{
fn index(&self, index: [std::ops::Range<usize>;D]) -> &Self::Output{
todo!()
// &self.data[index]
}
type Output = ArrayBase<D>;
}
There are several "blindspots" here (such as inability to "collapse" dimensions when range is empty or contains only one element, or mix range and integer slicing), but the key question is whether the ndarray users find it useful/appropriate to make the necessary changes to the crate to enable this at all.