此处a
的类型有什么问题?
fn foo(a: &[&[f64]], x: &[f64]) {
for i in 0..3 {
for j in 0..4 {
println!("{}", a[i][j]);
}
}
}
fn main() {
let A: [[f64; 4]; 3] = [
[1.1, -0.2, 0.1, 1.6],
[0.1, -1.2, -0.2, 2.3],
[0.2, -0.1, 1.1, 1.5],
];
let mut X: [f64; 3] = [0.0; 3];
foo(&A, &X);
}
我收到编译失败:
error[E0308]: mismatched types
--> src/main.rs:17:9
|
17 | foo(&A, &X);
| ^^ expected slice, found array of 3 elements
|
= note: expected type `&[&[f64]]`
found type `&[[f64; 4]; 3]`
答案 0 :(得分:14)
数组与切片的类型不同。值得注意的是,数组具有固定的大小,在编译时已知。切片具有固定大小,但仅在运行时知道。
我在这里看到两个直截了当的选择(见Levans answer for another)。第一种是将您的函数更改为仅接受对数组的引用(或整个数组,如果您可以复制它或不介意放弃所有权):
fn foo(a: &[[f64; 4]; 3], x: &[f64; 3]) {
for i in 0..3 {
for j in 0..4 {
println!("{}", a[i][j]);
}
}
}
fn main() {
let a = [
[1.1, -0.2, 0.1, 1.6],
[0.1, -1.2, -0.2, 2.3],
[0.2, -0.1, 1.1, 1.5],
];
let x = [0.0; 3];
foo(&a, &x);
}
另一个简单的改变是将你的声明引用到参考文献中:
fn foo(a: &[&[f64]], x: &[f64]) {
for i in 0..3 {
for j in 0..4 {
println!("{}", a[i][j]);
}
}
}
fn main() {
let a = [
&[1.1, -0.2, 0.1, 1.6][..],
&[0.1, -1.2, -0.2, 2.3][..],
&[0.2, -0.1, 1.1, 1.5][..],
];
let x = [0.0; 3];
foo(&a, &x);
}
注意第二个例子,当我们传入&a
和&x
时,我们可以使用对数组的引用的隐式强制转换为切片。但是,我们无法依赖于a
中的嵌套数据。 a
已被定义为数组数组,我们无法更改元素类型。
另外提醒 - 你真的应该在你的范围内使用切片的长度方法,否则你可以轻松地panic!
如果你走到最后。
fn foo(a: &[&[f64]], x: &[f64]) {
for i in 0..a.len() {
let z = &a[i];
for j in 0..z.len() {
println!("{}", z[j]);
}
}
}
我为满足Rust风格所做的其他风格改变:
snake_case
:
;
=
,
答案 1 :(得分:6)
作为Shepmaster对机制的良好解释的替代方法,实际上还有另一种方法可以使您的函数接受数组和切片(甚至{{1}的任意组合}}:它涉及使用具有AsRef
特征的泛型。
我的想法就是写下你的函数:
Vec
这是一个功能,但实际上非常简单:use std::convert::AsRef;
fn foo<S, T, U>(a: S, x: U)
where
T: AsRef<[f64]>,
S: AsRef<[T]>,
U: AsRef<[f64]>,
{
let slice_a = a.as_ref();
for i in 0..slice_a.len() {
let slice_aa = slice_a[i].as_ref();
for j in 0..slice_aa.len() {
println!("{}", slice_aa[j]);
}
}
}
必须通过S
特征强制转换为&[T]
,AsRef
必须强制转换为{T
1}}同样。同样&[f64]
必须强制U
,但我们不一定&[f64]
!
这样,U == T
可以是一个切片数组,一个数组数组,一个S
数组或切片,一个Vec数组......任何组合都是可能的,只要类型实现Vec
特征。
但请注意:AsRef
特征仅适用于最大尺寸为32的阵列。