0

I would like to write a function fn f<A>(xs: &mut [A; 9]) that reorders an array in-place from:

[a, b, c,
 d, e, f,
 g, h, i]

to:

[g, d, a,
 h, e, b,
 i, f, c]

I can't reassign the array due to moving elements out of array:

fn f1<A>(xs: &mut [A; 9]) {
    *xs = [xs[6], xs[3], xs[0], xs[7], xs[4], xs[1], xs[8], xs[5], xs[2]];
}
error[E0508]: cannot move out of type `[A; 9]`, a non-copy array
 --> src/lib.rs:2:12
  |
2 |     *xs = [xs[6], xs[3], xs[0], xs[7], xs[4], xs[1], xs[8], xs[5], xs[2]];
  |            ^^^^^
  |            |
  |            cannot move out of here
  |            move occurs because `xs[_]` has type `A`, which does not implement the `Copy` trait

I cannot do multiple mutable borrows:

fn f2<A>(xs: &mut [A; 9]) {
    std::mem::swap(&mut xs[0], &mut xs[6]);
}
error[E0499]: cannot borrow `xs[_]` as mutable more than once at a time
 --> src/lib.rs:2:32
  |
2 |     std::mem::swap(&mut xs[0], &mut xs[6]);
  |     -------------- ----------  ^^^^^^^^^^ second mutable borrow occurs here
  |     |              |
  |     |              first mutable borrow occurs here
  |     first borrow later used by call

There is no built-in function that does this transformation for me.

How to implement this?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
puritii
  • 1,069
  • 1
  • 7
  • 18
  • The answer to this question is to split the array into 9 different pieces? This is the most unreasonable solution I've ever heard of. – puritii Sep 29 '20 at 02:11
  • 2
    **The** answer? There are 3 duplicates, each of which have multiple overlapping answers. One answer shows how to use the swap that you've attempted, one shows how to move out of the array and back in, one shows splitting it up into 9 pieces. Then there are the various permutations of all the answers. [I'd personally use the unsafe one](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=50552ed11cf438fd147629ed4f1a37b1) if performance of this was important. – Shepmaster Sep 29 '20 at 02:22
  • 1
    To state the obvious, adding an `A: Copy` trait bound will make the first implementation work fine. If you only need this operation for standard number types, that may be the easiest option. – Sven Marnach Sep 29 '20 at 06:51
  • 2
    And for what it's worth, the [approach based on the `swap()` method](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=2b84b18f311c1c483578d85c7d7743c8) is just as fast on my machine as the unsafe version. – Sven Marnach Sep 29 '20 at 09:26

0 Answers0