如何在 if-let 语句中将复制的变量引入为可变变量?
How can I introduce a copied variable as mutable in a if-let statement?
我有一个 HashMap<i8, i8>
可以包含循环:
let mut x: HashMap<i8, i8> = HashMap::new();
x.insert(1, 6);
x.insert(3, 5);
x.insert(5, 1);
要获得 3
的最终值,它应该首先查找 x[3]
,然后是 x[5]
,最后是 x[1]
,这应该会产生 6
。我决定使用 while let
循环:
let mut y = x[&3]; // y: i8
while let Some(&z) = x.get(&y) {
y = z;
}
println!("{}", y);
x.insert(0, 0);
这很好用,但如果 3
不在地图中,它会 panic!
。因为我不想对 None
案例做任何事情,所以我想使用 if let
(类似于使用的 while let
)。
我尝试了一些符号:
if let Some(&y) = x.get(&3)
:复制值,但y是不可变的(y: i8
)
if let Some(mut y) = x.get(&3)
: y是可变的,但是值是借来的(mut y: &i8
)
if let mut Some(&y) = x.get(&3)
:我的目标:可变副本,但语法无效 (mut y: i8
)
(所有变体都可以在 Rust Playground 找到,但您需要注释掉第三次尝试,因为它是无效语法)
我不会争论第二个变体,但我需要将值插入到 if let
正文中的映射中。由于地图仍然是借来的,我不能再插入了。我只需要复制 Some(y)
中的值,并且 y
是可变的,以便借用检查器得到满足,我可以进行递归查找。
你的方法#1 是一个完全正确的匹配,你只需要使 y
变量可变。一种可能性是将 Option<&i8>
转换为 Option<i8>
,以便在模式中使用 mut y
。例如,Option::map
可以取消引用值:
if let Some(mut y) = x.get(&3).map(|ref| *ref) {
由于 Copy
暗示(便宜)Clone
,您可以使用 Option::cloned()
:
表达相同的意思
if let Some(mut y) = x.get(&3).cloned() {
从 Rust 1.35 开始,您可以使用 Option::copied()
,它只为 Copy
类型定义并且只复制值:
if let Some(mut y) = x.get(&3).copied() {
另一种可能性是保留您的方法 #1 as-is,但只需在 if let
块中引入一个单独的可变变量即可更正它:
if let Some(&y) = x.get(&3) {
let mut y = y;
...
您的代码基本有效:
use std::collections::HashMap;
fn main() {
let mut x: HashMap<i8, i8> = HashMap::new();
x.insert(1, 6);
x.insert(3, 5);
x.insert(5, 1);
let mut key = 3;
while let Some(&z) = x.get(&key) {
key = z;
}
println!("{}", key);
x.insert(key, 0);
}
这里,key
作为最后一个不匹配的键被留下。
我有一个 HashMap<i8, i8>
可以包含循环:
let mut x: HashMap<i8, i8> = HashMap::new();
x.insert(1, 6);
x.insert(3, 5);
x.insert(5, 1);
要获得 3
的最终值,它应该首先查找 x[3]
,然后是 x[5]
,最后是 x[1]
,这应该会产生 6
。我决定使用 while let
循环:
let mut y = x[&3]; // y: i8
while let Some(&z) = x.get(&y) {
y = z;
}
println!("{}", y);
x.insert(0, 0);
这很好用,但如果 3
不在地图中,它会 panic!
。因为我不想对 None
案例做任何事情,所以我想使用 if let
(类似于使用的 while let
)。
我尝试了一些符号:
if let Some(&y) = x.get(&3)
:复制值,但y是不可变的(y: i8
)if let Some(mut y) = x.get(&3)
: y是可变的,但是值是借来的(mut y: &i8
)if let mut Some(&y) = x.get(&3)
:我的目标:可变副本,但语法无效 (mut y: i8
)
(所有变体都可以在 Rust Playground 找到,但您需要注释掉第三次尝试,因为它是无效语法)
我不会争论第二个变体,但我需要将值插入到 if let
正文中的映射中。由于地图仍然是借来的,我不能再插入了。我只需要复制 Some(y)
中的值,并且 y
是可变的,以便借用检查器得到满足,我可以进行递归查找。
你的方法#1 是一个完全正确的匹配,你只需要使 y
变量可变。一种可能性是将 Option<&i8>
转换为 Option<i8>
,以便在模式中使用 mut y
。例如,Option::map
可以取消引用值:
if let Some(mut y) = x.get(&3).map(|ref| *ref) {
由于 Copy
暗示(便宜)Clone
,您可以使用 Option::cloned()
:
if let Some(mut y) = x.get(&3).cloned() {
从 Rust 1.35 开始,您可以使用 Option::copied()
,它只为 Copy
类型定义并且只复制值:
if let Some(mut y) = x.get(&3).copied() {
另一种可能性是保留您的方法 #1 as-is,但只需在 if let
块中引入一个单独的可变变量即可更正它:
if let Some(&y) = x.get(&3) {
let mut y = y;
...
您的代码基本有效:
use std::collections::HashMap;
fn main() {
let mut x: HashMap<i8, i8> = HashMap::new();
x.insert(1, 6);
x.insert(3, 5);
x.insert(5, 1);
let mut key = 3;
while let Some(&z) = x.get(&key) {
key = z;
}
println!("{}", key);
x.insert(key, 0);
}
这里,key
作为最后一个不匹配的键被留下。