I can destructure a vector of tuples by taking a slice of a vector and references to the items within the tuple:
let items = vec![("Peter".to_string(), 180)];
if let [(ref name, ref age)] = items.as_slice() {
println!("{} scored {}", name, age);
};
How can I destructure the vector directly, moving the items out of the tuple. Something like this:
let items = vec![("Peter".to_string(), 180)];
if let [(name, age)] = items {
println!("{} scored {}", name, age);
};
Compiling the above results in the error:
error[E0529]: expected an array or slice, found `std::vec::Vec<(std::string::String, {integer})>`
--> src/main.rs:4:12
|
4 | if let [(name, age)] = items {
| ^^^^^^^^^^^^^ pattern cannot match with input type `std::vec::Vec<(std::string::String, {integer})>`
You are asking two disjoint questions at once:
The second is easy:
let item = ("Peter".to_string(), 180);
let (name, score) = item;
You don't need the if let
syntax because there no way for this pattern-matching to fail. Of course, you can't use item
after destructuring it because you've transferred ownership from item
to name
and score
.
The first question is harder, and gets to a core part of Rust. If you transfer ownership out of a vector, then what state is the vector in? In C, you would have some undefined chunk of memory sitting in the vector, waiting to blow apart your program. Say you called free
on that string, then what happens when you use the thing in the vector that pointed to the same string?
There are a few ways to solve it...
let items = vec![("Peter".to_string(), 180)];
if let Some((name, score)) = items.first() {
println!("{} scored {}", name, score);
}
Here, we grab a reference to the first item and then references to the name and score. Since the vector may not have any items, it returns an Option
, so we do use if let
. The compiler will not let us use these items any longer than the vector lives.
let mut items = vec![("Peter".to_string(), 180)];
let (name, score) = items.remove(0); // Potential panic!
println!("{} scored {}", name, score);
Here, we remove
the first item from the array. The vector no longer owns it, and we can do whatever we want with it. We destructure it immediately. items
, name
and score
will all have independent lifetimes.
let items = vec![("Peter".to_string(), 180)];
for (name, score) in items {
println!("{} scored {}", name, score);
}
Here, we consume the vector, so it is no longer available to use after the for
loop. Ownership of name
and score
is transferred to the variables in the loop binding.
let items = vec![("Peter".to_string(), 180)];
let (name, score) = items[0].clone(); // Potential panic!
println!("{} scored {}", name, score);
Here, we make new versions of the items in the vector. We own the new items, and the vector owns the original ones.
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