I have a HashMap<i8, i8>
which could contain cycles:
let mut x: HashMap<i8, i8> = HashMap::new();
x.insert(1, 6);
x.insert(3, 5);
x.insert(5, 1);
To get the final value for 3
, it should first lookup x[3]
, then x[5]
and finally x[1]
which should yield 6
. I decided to use a while let
loop:
let mut y = x[&3]; // y: i8
while let Some(&z) = x.get(&y) {
y = z;
}
println!("{}", y);
x.insert(0, 0);
This works fine, but it would panic!
if 3
is not in the map. As I don't want to do anything about the None
case, I want to use a if let
(similar to the while let
used).
I have tried some notations:
if let Some(&y) = x.get(&3)
: copies the value, but y is immutable (y: i8
)if let Some(mut y) = x.get(&3)
: y is mutable, but the value is borrowed (mut y: &i8
)if let mut Some(&y) = x.get(&3)
: my target: mutable copy, but invalid syntax (mut y: i8
)(All variants are available at Rust Playground, but you need to comment out the third try, as it is invalid syntax)
I would not argue about the second variant, but I need to insert values into my map in the body of the if let
. As the map remains borrowed, I can't insert anymore. All I would need is that the value in Some(y)
is copied, and y
is mutable, so that the borrow checker is satisfied and I can do my recursive lookups.
Your approach #1 is a perfectly correct match, you just need to make the y
variable mutable. One possibility is to convert Option<&i8>
to Option<i8>
, enabling the use of mut y
in the pattern. For example, Option::map
can dereference the value:
if let Some(mut y) = x.get(&3).map(|ref| *ref) {
Since Copy
implies (cheap) Clone
, you can express the same using Option::cloned()
:
if let Some(mut y) = x.get(&3).cloned() {
As of Rust 1.35, you can use Option::copied()
, which is guaranteed to just copy the value (and fails to compile if the value is not Copy
):
if let Some(mut y) = x.get(&3).copied() {
Another possibility is to leave your approach #1 as-is, but correct it simply by introducing a separate mutable variable inside the if let
block:
if let Some(&y) = x.get(&3) {
let mut y = y;
...