I have been playing with Rust by porting my Score4 AI engine to it - basing the work on my functional-style implementation in OCaml. I specifically wanted to see how Rust fa
This here
moves_and_scores.iter()
gives you an iterator over borrowed vector elements. If you follow the API doc what type this is, you'll notice that it's just the iterator for a borrowed slice and this implements Iterator
with Item=&T
where T
is (u32, i32)
in your case.
Then, you use find
which takes a predicate which takes a &Item
as parameter. Sice Item
already is a reference in your case, the predicate has to take a &&(u32, i32)
.
pub trait Iterator {
...
fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
where P: FnMut(&Self::Item) -> bool {...}
... ^
It was probably defined like this because it's only supposed to inspect the item and return a bool. This does not require the item being passed by value.
If you want an iterator over (u32, i32)
you could write
moves_and_scores.iter().cloned()
cloned()
converts the iterator from one with an Item
type &T
to one with an Item
type T
if T
is Clone
. Another way to do it would be to use into_iter()
instead of iter()
.
moves_and_scores.into_iter()
The difference between the two is that the first option clones the borrowed elements while the 2nd one consumes the vector and moves the elements out of it.
By writing the lambda like this
|&&(_, score)| score == target_score
you destructure the "double reference" and create a local copy of the i32
. This is allowed since i32
is a simple type that is Copy
.
Instead of destructuring the parameter of your predicate you could also write
|move_and_score| move_and_score.1 == target_score
because the dot operator automatically dereferences as many times as needed.