我有一个传递给函数的3x3矩阵(2D数组):
let matrix: [[i32; 3]; 3] = [
[0, 0, 0],
[0, 1, 0],
[0, 0, 0]
];
filter::convolve(&mut image, matrix, 1).unwrap();
该函数目前已硬连线以接受3x3矩阵:
pub fn convolve(src: &mut Image, matrix: [[i32; 3]; 3], divisor: i32) -> Result<&mut Image, String> {
// ...
}
如何将3x3、5x5或任意大小的矩阵传递给同一函数?
数组具有固定大小,在编译时确定。切片具有固定的大小,在运行时确定。
最简单的方法是接受一个切片:
fn convolve(matrix: &[&[i32]]) {
println!("{:?}", matrix);
}
fn main() {
let matrix = &[
&[0, 0, 0][..],
&[0, 1, 0][..],
&[0, 0, 0][..],
];
convolve(matrix);
}
有点烦人,因为您必须使用切片语法(&foo[..]
)将文字数组转换为切片。您还可以接受泛型,从而可以接受上述内容,但也可以接受任何可以转换为切片的内容:
fn convolve<T, I>(matrix: &[T])
where
T: AsRef<[I]>,
I: std::fmt::Debug,
{
for part in matrix {
println!("{:?}", part.as_ref());
}
}
fn main() {
let matrix = &[
[0, 0, 0],
[0, 1, 0],
[0, 0, 0],
];
convolve(matrix);
}
正如kosinix指出的那样,不能保证&[&[i32]]
行的长度相等。可能会有一个参差不齐的数组。
对此的运行时解决方案是遍历所有行并确保所有长度都相同。这可以减少到只检查一次,如果你创建一个NEWTYPE为矩阵你已经验证:
struct Matrix<'a, T: 'a>(&'a [&'a [T]]);
impl<'a, T> Matrix<'a, T> {
fn new(slice: &'a [&'a [T]]) -> Result<Self, ()> {
if slice.is_empty() {
return Ok(Matrix(slice));
}
let (head, tail) = slice.split_at(1);
let expected = head[0].len();
if tail.iter().map(|row| row.len()).all(|l| l == expected) {
Ok(Matrix(slice))
} else {
Err(()) // return a real error here
}
}
}
现在,只要有一个Matrix
,就可以确保各行的长度都相同。
编译时解决方案...尚不存在。这些称为const泛型。该提议的语法是
fn convolve<const N: usize>(matrix: [[i32; N]; N])
有一些稳定的解决方法(例如generic-array),但是可能以一种或另一种方式受到限制。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句