When iterating a list of tuples, the & is needed to make it work. Thus this will work ...
for &(a, b, c) in [("hello", 1.0, 5), ("world", 2.0, 2)].iter() {
println!("{} {} {}", a, b, c);
}
but that won't ...
for (a, b, c) in [("hello", 1.0, 5), ("world", 2.0, 2)].iter() {
println!("{} {} {}", a, b, c);
}
// type mismatch resolving `<core::slice::Iter<'_, (&str, _, _)> as core::iter::Iterator>::Item == (_, _, _)`:
// expected &-ptr,
found tuple [E0271]
I am sure it has to do with intricacies of the destructuring syntax that I have not yet fully internalised.
Can you explain which syntactical truth is behind the ampersand ?
It's because the iter method for an array [T] returns an iterator that yields &T values. That's why the compiler says "expected &-ptr, found tuple [E0271]".
So why's that? Well, in general, you can't copy T. Unless the code assumes a more restrictive bound of T: Copy or T: Clone, it can only move values of type T.
This is a problem for arrays because there's no way to move a single element out of an array; doing so would invalidate the whole thing.
Aside:
Vecand co. get around this by implementing additional logic inunsafeblocks to make it work. Containers may also provideinto_iterwhich gives you an iterator that incrementally consumes the container, allowing you to move values out.
Because you want the array iter method to work for all arrays, it instead yields immutable references to each element in turn.
As a result, you're trying to destructure a &(&str, f32, i32), not a (&str, f32, i32), hence the additional &. Rust doesn't like implicitness, so you have to explicitly destructure the reference. This also helps make it clear that there's a dereference and a copy happening here.
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