Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rust Lang: What is "if let Some(x) = x" doing?

Tags:

rust

I'm working on a rust project written a couple of years ago, and have come across this piece of code, which is literally:

let mut values = vec![];
for x in maybe_values {
    if let Some(x) = x {
        values.push(Arc::new(x));
    }
}

I understand that "if let" introduces a pattern-matching if (Which seems to be a poor re-use of the keyword "let", but I will get over that - If anyone can help me with a mental mnemonic to make sense of "let" here, please do!).

But what is the test Some(x) = x doing?

From my testing, it seems to be a trick/idiom to both a) test that the loop variant 'x' is Some(), and also b) end up with the unwrap()ped value in x.

But I can't fully explain it to myself, and can't find reference to this being an idiom anywhere.

Hope you can help my Rust education path. Thanks.

like image 967
spechter Avatar asked Sep 02 '25 11:09

spechter


2 Answers

This is a shorthand for using a full match statement when you only care about matching a single use case.

So this block of code:

if let x = y {
   foo();
} else {
   bar();
}

Is equivalent to using a full match:

match y {
    x => {
        foo();
    }
    _ => {
        bar();
    }
}

For your specific case, it is equivalent to this. The inner x uses the same name as the outer variable which can be confusing, but they are two separate values.

let mut values = vec![];
for x in maybe_values {
    match x {
        Some(y) => values.push(Arc::new(y)),
        _ => {},
    }
}
like image 172
Locke Avatar answered Sep 04 '25 09:09

Locke


There are two completely different variables in play here. It's equivalent to.

let mut values = vec![];
for x_1 in maybe_values {
  if let Some(x_2) = x_1 {
    values.push(Arc::new(x_2));
  }
}

In Rust, the right-hand side of a let is evaluated with the left-hand variable not in scope, so when the if let is evaluated, the outer x is still in-scope. Then, if it's a Some value, we make a new variable x which contains the inside of the Option. This variable shadows the previous x, making it inaccessible inside the if statement (in the same way that a function argument called x would render a global variable named x inaccessible by shadowing).

like image 37
Silvio Mayolo Avatar answered Sep 04 '25 09:09

Silvio Mayolo