Reputation: 33
Given the following function:
fn some_function<K, F: Fn(K) -> K>(f: F, vs: Vec<K>) -> Vec<K> {
let mut index = 0;
let new_vec = vs.iter().map(|x| {
index += 1;
for _ in 1 .. index {
x = f(x); // <- error here: mismatched types expected reference `&K` found type parameter `K`
}
*x
}).collect();
new_vec
}
How can i make it work ?
Upvotes: 0
Views: 846
Reputation: 299820
There are 3 types of variables in Rust:
In turn, this maps to 3 different iteration functions:
.into_iter()
will return an iterator over values..iter()
will return an iterator over shared references..iter_mut()
will return an iterator over mutable references.You simply didn't pick the right function, and should have used into_iter
instead.
fn some_function<K, F: Fn(K) -> K>(f: F, vs: Vec<K>) -> Vec<K> {
vs
.into_iter()
.enumerate()
.map(|(index, mut x)| {
for _ in 0..index {
x = f(x);
}
x
}).collect()
}
Additionally:
enumerate
will allow you to get an index of each element as you iterate, so that you do not have to maintain the index yourself.i
items, you want 0..i
, not 1..i
.For performance, however, it would be better to in-place modify the elements if possible. This allows reusing buffers, including the vector's own buffer. The result would be:
fn some_function<K, F: Fn(&mut K)>(f: F, vs: &mut Vec<K>) {
vs
.iter_mut()
.enumerate()
.for_each(|(index, x)| {
for _ in 0..index {
f(x);
}
});
}
Upvotes: 2
Reputation: 8678
This example doesn't work because .iter()
will not produce an iterator of owned variables, but references to elements of vs
. You could patch your code by turning it into into_iter()
:
fn some_function<K>(f: impl Fn(K) -> K, vs: Vec<K>) -> Vec<K> {
let mut index = 0;
vs.into_iter()
.map(|mut x| {
index += 1;
for _ in 1..index { x = f(x); }
x
})
.collect()
}
But you don't need to keep track of index
:
fn some_function<K>(f: impl Fn(K) -> K, vs: Vec<K>) -> Vec<K> {
vs
.into_iter()
.enumerate()
.map(|(i, mut x)| {
for _ in 0..i { x = f(x); }
x
})
.collect()
}
Upvotes: 1