即使声明为变量,变量也表示不可变

时间:2017-11-11 21:05:05

标签: rust immutability mutable

我通过使用布尔值向量表示数字来重新创建二进制算术运算。由于每个向量的大小可以变化,我做了一个函数来匹配每个向量的长度:

fn match_lengths(mut bit_vec0: Vec<bool>, mut bit_vec1: Vec<bool>) -> (Vec<bool>, Vec<bool>) {
    {
        let (mut shorter, longer) = if bit_vec0.len() < bit_vec1.len() {
            (&bit_vec0, &bit_vec1)
        } else {
            (&bit_vec1, &bit_vec0)
        };
        let bit_sign = match shorter.last() {
            Some(content) => *content,
            None => false,
        };

        for _ in shorter.len()..longer.len() {
            shorter.push(bit_sign);
        }
    }

    (bit_vec0, bit_vec1)
}

我收到错误

error[E0596]: cannot borrow immutable borrowed content `*shorter` as mutable
  --> src/main.rs:15:13
   |
15 |             shorter.push(bit_sign); // Error here
   |             ^^^^^^^ cannot borrow as mutable

即使我用mut说明符声明了它。

1 个答案:

答案 0 :(得分:2)

shorter的类型是引用,更准确地说是&Vec<bool>,这意味着它引用了Vec<bool>,它不允许变异< SUP> 1

将变量声明为mut shorter只会使shorter变量变为可变,从而允许您使用shorter = ...分配使其引用不同的Vec<bool>。无论变量的可变性如何,都不允许类型为&Vec<bool>的共享引用来改变它所引用的对象。

您需要做的是使用&mut Vec<bool>&mut bit_vec0制作&mut bit_vec1类型的可变引用。此更改使代码编译,此时shorter不再需要mut

最后,这与问题无关,match_lengths按值接受bit_vec0bit_vec1,修改它们并返回它们。虽然这当然有效,但接受可变引用更为惯用。这样的方法对于呼叫者来说更符合人体工程学,并且更清楚地表明该功能实际上不会返回&#34;什么,它真的修改了现有的对象。

通过这些修改,函数如下所示:

fn match_lengths(bit_vec0: &mut Vec<bool>, bit_vec1: &mut Vec<bool>) {
    let (shorter, longer) = if bit_vec0.len() < bit_vec1.len() {
        (bit_vec0, bit_vec1)
    } else {
        (bit_vec1, bit_vec0)
    };
    let bit_sign = match shorter.last() {
        Some(content) => *content,
        None => false,
    };
    for _ in shorter.len()..longer.len() {
        shorter.push(bit_sign);
    }
}

1 这听起来很像C ++的const,但Rust中的保证甚至比const更强:不仅是共享(非mut)引用不允许改变它引用的对象,但也不是其他任何人! Rust的编译器和运行时阻止在对该对象的任何共享引用存在时创建对象的mut引用。