Reputation: 32008
I have a function called new_vec
. It takes two vectors and creates a new one, by performing an elementwise operation on the pair of elements from the zipped vectors.
fn main() {
let v1s = vec![1, 0, 1];
let v2s = vec![0, 1, 1];
let v3s = new_vec(v1s, v2s);
println!("{:?}", v3s) // [1, 1, 2]
}
fn new_vec(v1s: Vec<i32>, v2s: Vec<i32>) -> Vec<i32> {
let mut v3s = Vec::<i32>::new();
for (v1, v2) in v1s.iter().zip(v2s.iter()) {
v3s.push(v1 + v2) // would also like to use -
}
v3s
}
I want to have a new_vec
function for the common binary operation that is possible to use on two integers, such as +
, -
, /
, *
.
How do I do this? I can imagine two ways: macros and closures. A minimal example of how to do this in the best way, for example with +
and -
would be appreciated.
Upvotes: 0
Views: 99
Reputation: 22273
I would pass a closure:
fn new_vec<F>(v1s: &[i32], v2s: &[i32], foo: F) -> Vec<i32>
where F: Fn(i32, i32) -> i32
{
let mut v3s = Vec::<i32>::new();
for (&v1, &v2) in v1s.iter().zip(v2s.iter()) {
v3s.push(foo(v1, v2))
}
v3s
}
fn main() {
let v1s = vec![1, 0, 1];
let v2s = vec![0, 1, 1];
let v3s = new_vec(&v1s, &v2s, |x, y| x - y);
let v4s = new_vec(&v1s, &v2s, |x, y| x + y);
println!("{:?}", v3s); // [1, -1, 0]
println!("{:?}", v4s); // [1, 1, 2]
}
Note the change in the first two parameters; if your function doesn't need to consume its arguments, references are preferable to Vec
tors - in this case &[i32]
.
This implementation is not too efficient because the resulting Vec
tor is extended incrementally; it's better if you modified it as follows to reduce the number of allocations:
fn new_vec<F>(v1s: &[i32], v2s: &[i32], foo: F) -> Vec<i32>
where F: Fn(i32, i32) -> i32
{
v1s.iter().zip(v2s.iter()).map(|(&x, &y)| foo(x, y)).collect()
}
Upvotes: 5