即使声明为可变的,变量也被认为是不可变的
Variable said to be immutable even if declared as 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
说明符声明了它。
shorter
的类型是 reference,更准确地说是 &Vec<bool>
,这意味着它引用了 Vec<bool>
它是不允许突变1.
将变量声明为 mut shorter
只会使 shorter
变量可变,例如使用 shorter = ...
赋值使其引用不同的 Vec<bool>
。无论变量的可变性如何,&Vec<bool>
类型的共享引用都不允许改变它所引用的对象。
您需要做的是使用 &mut bit_vec0
和 &mut bit_vec1
创建类型 &mut Vec<bool>
的可变引用。此更改使代码可以编译,此时 shorter
不再需要 mut
.
最后,这与问题无关,match_lengths
按值接受 bit_vec0
和 bit_vec1
,修改它们,并 returns 它们。虽然这确实有效,但接受可变引用更为惯用。这种方法对调用者来说更符合人体工程学,并且更清楚地表明该函数实际上并没有 "return" 任何东西,它实际上修改了现有对象。
经过这些修改,函数如下所示:
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
引用,同时存在对该对象的任何共享引用。
我正在通过用布尔值向量表示数字来重新创建二进制算术运算。由于每个向量的大小可能不同,我做了一个函数来匹配每个向量的长度:
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
说明符声明了它。
shorter
的类型是 reference,更准确地说是 &Vec<bool>
,这意味着它引用了 Vec<bool>
它是不允许突变1.
将变量声明为 mut shorter
只会使 shorter
变量可变,例如使用 shorter = ...
赋值使其引用不同的 Vec<bool>
。无论变量的可变性如何,&Vec<bool>
类型的共享引用都不允许改变它所引用的对象。
您需要做的是使用 &mut bit_vec0
和 &mut bit_vec1
创建类型 &mut Vec<bool>
的可变引用。此更改使代码可以编译,此时 shorter
不再需要 mut
.
最后,这与问题无关,match_lengths
按值接受 bit_vec0
和 bit_vec1
,修改它们,并 returns 它们。虽然这确实有效,但接受可变引用更为惯用。这种方法对调用者来说更符合人体工程学,并且更清楚地表明该函数实际上并没有 "return" 任何东西,它实际上修改了现有对象。
经过这些修改,函数如下所示:
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
引用,同时存在对该对象的任何共享引用。