In my function I need to rotate a VecDeque a certain amount of times, always in the same direction that depends on the input, with a value that never changes. So I started envisioning a solution like the following, where I can just assign the right rotation function to a function pointer and call it inside the loop to avoid repeating a useless branching.
use std::collections::VecDeque;
fn example(k: isize) -> Vec<usize> {
let mut queue: VecDeque<usize> = VecDeque::from(vec![1, 2, 3, 4, 5]);
let mut order = Vec::new();
let rotation = 1 - k;
let (amount, rotate) = match rotation >= 0 {
true => (
rotation as usize,
VecDeque::rotate_right as fn(_, _),
),
_ => (
rotation.unsigned_abs(),
VecDeque::rotate_left as fn(_, _),
),
};
while !queue.is_empty() {
rotate(&mut queue, amount % queue.len());
order.push(queue.pop_front().unwrap());
}
order
}
This would have worked, but as soon as I wrote the loop I got all manners of errors related to mutable and immutable borrows of queue. After some fiddling and the help of other people, it seems the most reasonable way is to write the code like this, with the differences highlighted by comments.
use std::collections::VecDeque;
fn example(k: isize) -> Vec<usize> {
let mut queue: VecDeque<usize> = VecDeque::from(vec![1, 2, 3, 4, 5]);
let mut order = Vec::new();
let rotation = 1 - k;
let (amount, rotate) = match rotation >= 0 {
true => (
rotation as usize,
VecDeque::rotate_right as fn(&mut _, _),
), // HERE ^
_ => (
rotation.unsigned_abs(),
VecDeque::rotate_left as fn(&mut _, _),
), // HERE ^
};
while !queue.is_empty() {
let len = queue.len();
rotate(&mut queue, amount % len);
// HERE ^
order.push(queue.pop_front().unwrap());
}
order
}
Now, why exactly is the &mut required as if it provided a better suggestion for allowing the compiler to correctly infer the type of the function pointer? And inside the loop I also need to assign the current length of the queue to a separate variable first, but if I were in a case with simpler code it would have worked regardless like in the first snippet.