Reputation: 2368
This works because Iterator
implements rev()
where self
is a DoubleEndedIterator
:
let vec: Vec<i32> = Vec::new();
for x in vec.iter().rev() {
//Do stuff
}
However, if I change vec.iter().rev()
to &vec.rev()
it won't compile because:
no method named `rev` found for type `std::vec::Vec<i32>` in the current scope
Furthermore:
the method `rev` exists but the following trait bounds were not satisfied: `std::vec::Vec<i32> : std::iter::Iterator`, `[i32] : std::iter::Iterator`
But doesn't a for loop implicitly call IntoIterator
? Is &vec
or vec.iter()
considered idiomatic Rust?
Upvotes: 27
Views: 25539
Reputation: 981
As indicated by the others answer, it is due to the precedence of the &
operator.
You can use parenthesis to clarify that &
is referring to v
and not the result of rev()
.
This won't compile:
let vec: Vec<i32> = Vec::new();
for x in &vec.iter().rev() {
//Do stuff
}
This will compile:
let vec: Vec<i32> = Vec::new();
for x in (&vec).iter().rev() {
//Do stuff
}
It also works if the reference is a variable. As there is no ambiguity that &
is referring to v
:
fn main() {
let v = vec!["Can", "I", "talk", "backward"];
let yoda = &v; // reference to the vector
for word in yoda.into_iter().rev() {
println!("{}", word);
}
}
Upvotes: 1
Reputation: 430290
This is just basic precedence of the &
operator. In the first case, each method is called in turn:
vec.iter().rev()
(vec.iter()).rev() // same
In the second case, the &
binds after all the methods:
&vec.rev()
&(vec.rev()) // same
Generally, use &vec
when you can, but when you need to use iterator adapter methods, use iter
or into_iter
.
Upvotes: 16
Reputation: 14021
If you're just looping over the Vec
, then &vec
is idiomatic. This works because &Vec<T>
implements IntoIterator
, which is what the for loop uses.
However if you want to call Iterator
methods such as rev
, filter
, etc., you need an actual Iterator
(since Vec
doesn't implement Iterator
, only IntoIterator
).
So this:
for x in &vec.rev() {
...
}
is equivalent to:
for x in (&vec.rev()).into_iter() {
...
}
i.e. there's no chance to use IntoIterator
before trying to call Iterator
methods.
Upvotes: 27