在Rust中创建矢量矢量

时间:2016-02-25 14:30:28

标签: matrix vector rust

此代码无法编译:

fn main() {
    let m1 = vec![1, 2, 3];
    let m2 = vec![&m1, &m1, &m1];
    let m3 = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];

    for i in &m2 {
        for j in i {
            println!("{}", j);
        }
    }

    for i in &m3 {
        for j in i {
            println!("{}", j);
        }
    }
}
error[E0277]: the trait bound `&&std::vec::Vec<{integer}>: std::iter::Iterator` is not satisfied
 --> src/main.rs:8:18
  |
8 |         for j in i {
  |                  ^ `&&std::vec::Vec<{integer}>` is not an iterator; maybe try calling `.iter()` or a similar method
  |
  = help: the trait `std::iter::Iterator` is not implemented for `&&std::vec::Vec<{integer}>`
  = note: required by `std::iter::IntoIterator::into_iter`
  1. m2m3的不同之处在于m3不会导致任何问题,但m2会阻止编译?

  2. 有没有更简单的方法来创建...的矢量向量到任何所需的深度?我的工作方式(m3)看起来很笨重。

1 个答案:

答案 0 :(得分:5)

  

m2m3 ...

的区别如何?

逐步检查类型。 m1的类型为Vec<isize>(它也可以是任何其他整数类型,但我现在认为它是isize)。为什么?因为vec![]宏中的元素属于isize类型。现在您正在创建m2

let m2 = vec![&m1, &m1, &m1];

此宏中元素的类型是什么?我们已经说m1的类型为Vec<isize>,因此&m1的类型为&Vec<isize>。因此,m2的结果类型为Vec<&Vec<isize>>(向其他向量添加引用的向量)。

但是,m3的类型为Vec<Vec<isize>>,因为(外部)vec![]宏中的元素属于Vec<isize>类型(无引用!)。

提示to easily check the type of any variable(例如foo),输入:

let _: () = foo;

这将导致编译器错误,告诉您foo的类型。

  

... m3导致没有问题,但m2会阻止编译?

现在我们知道了m2m3的类型,让我们看一下循环。 for循环通过接受实现IntoIterator的内容来工作。您正在传递&m2,其类型为&Vec<&Vec<isize>>(请注意两个引用)。 We can seeIntoIterator确实是为了引用向量而实现的:

impl<T> IntoIterator for &Vec<T> {
    type Item = &T
    // ...
}

这意味着您将获得一个迭代器,该迭代器将对内部类型Ttype Item = &T)的引用进行吐出。我们的内部类型m2&Vec<isize>,因此我们将获得&&Vec<isize>类型的项目(两个引用!)。您的变量i具有此类型。

然后你想用这个内循环再次迭代:

for j in i { ... }

i具有此双引用类型,并且该类型没有IntoIterator的实现。要迭代它,你必须取消引用它:

for j in *i { ... }

甚至更好:通过在外部循环中使用模式匹配将其剥离,使i成为&Vec<isize>类型(一个引用!):

for &i in &m2 { ... }

您的m3循环执行相同操作,但由于m3属于另一种类型(少了一个参考),它可以正常工作(我希望您能看到原因)。

  

是否有更简单的方法来创建向量的矢量...到任何所需的深度

即使m2有效,它也不会与m3保持相同的值。要制作m2类型的Vec<Vec<isize>>(例如m3),您应该clone m1而不是参考它。

let m2 = vec![m1.clone(), m1.clone(), m1.clone()];

我们可以使用宏的vec![_; _]形式做得更好:

let m2 = vec![m1; 3];   // three times the value of `m1`

作为最后一点,您应该使用嵌套的Vec来考虑 not 。嵌套会产生开销,因为值分布在整个内存中而不是在一个位置。