How do I convert an array of size N, into another array of size N (or a tuple with N elements, I don't care) by applying a function to all of the elements of the source one by one?
Here are a few solutions that I found, but I'm not really satisfied. TL; DR: I think the last one is the best one.
If you really need it the result to be a [i32; 3], then yes, your last version is the way to do it in general. For such short arrays as 3 items, i think the first is good as well.
What i woud use is:
let source = [1, 2, 3];
let dest: Vec<usize> = source.iter().map(|x| x*x).collect().
Then dest is a dynamically allocated Vec and not really an array, but you can still borrow it as a slice, so it only matters if you have a strong reason to avoid allocations.
What I dislike with my last version is that the variable must be mut, and the compiler doesn't verify if all elements are initialized with a sensible value. The before the last version would be much better, but unfortunately it doesn't compiles (yet).
And yes the version with Vec is good too, but I definitively doesn't like to allocate for no reason (especially since Vec doesn't have small buffer optimization, so it will always allocate). It's the kind of small performance degradation that will never be fixed, but will slowly accumulate over time.
let source = [1, 2, 3];
let dest = {
let mut dest = [0; 3];
for (i, value) in source.iter().enumerate() {
dest[i] = f(value);
}
dest
};
The differences is that dest is only mutable in the initializing block, and that the enumerate() removes the need for indexing source. If that is better or not is probably a matter of tast, as dest is still indexed.
I generally find them much nicer to work with than arrays, and you can convert back and forth (as long as the arrayvec is full, at least, which it will be when you iterate like this).