I've seen a few other questions and answers stating that let _ = foo()
destroys the result at the end of the statement rather than at scope exit, which is what let _a = foo()
does.
I am unable to find any official description of this, nor any rationale for this syntax.
I'm interested in a few inter-twined things:
An End is a statement in VBA that has multiple forms in VBA applications. One can put a simple End statement anywhere in the code. It will automatically stop the execution of the code. One can use the End statement in many procedures like to end the sub procedure or to end any Loop function like “End If.”
This error has the following cause and solution: An If statement is used without a corresponding End If statement. A multiline If statement must terminate with a matching End If statement.
The End statement stops code execution abruptly, without invoking the Unload, QueryUnload, or Terminate event, or any other Visual Basic code. Code you have placed in the Unload, QueryUnload, and Terminate events of forms and class modules is not executed.
In VBA Do Until Loop, we need to define criteria after the until statement which means when we want the loop to stop and the end statement is the loop itself. So if the condition is FALSE it will keep executing the statement inside the loop but if the condition is TRUE straight away it will exit the Do Until statement.
Is it simply natural fall-out from Rust's binding / destructuring rules?
Yes. You use _
to indicate that you don't care about a value in a pattern and that it should not be bound in the first place. If a value is never bound to a variable, there's nothing to hold on to the value, so it must be dropped.
All the Places Patterns Can Be Used:
match
Armsif let
Expressionswhile let
Conditional Loopsfor
Loopslet
StatementsIs there even a mention of it in the official documentation?
Ignoring an Entire Value with _
Of note is that _
isn't a valid identifier, thus you can't use it as a name:
fn main() {
let _ = 42;
println!("{}", _);
}
error: expected expression, found reserved identifier `_`
--> src/main.rs:3:20
|
3 | println!("{}", _);
| ^ expected expression
achieved using explicit scoping
I suppose you could have gone this route and made expressions doing this just "hang around" until the scope was over, but I don't see any value to it:
let _ = vec![5];
vec![5]; // Equivalent
// Gotta wait for the scope to end to clean these up, or call `drop` explicitly
The only reason that you'd use let _ = foo()
is when the function requires that you use its result, and you know that you don't need it. Otherwise, this:
let _ = foo();
is exactly the same as this:
foo();
For example, suppose foo
has a signature like this:
fn foo() -> Result<String, ()>;
You will get a warning if you don't use the result, because Result
has the #[must_use]
attribute. Destructuring and ignoring the result immediately is a concise way of avoiding this warning in cases where you know it's ok, without introducing a new variable that lasts for the full scope.
If you didn't pattern match against the result then the value would be dropped as soon as the foo
function returns. It seems reasonable that Rust would behave the same regardless of whether you explicitly said you don't want it or just didn't use it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With