A non in-place version of rotate?

Hi,
Looking into the rotate function and noted that there is not a rotated version that returns a copy instead of rotating in-place or even a lazy view version like e.g. RotatedCollection.

Just curious if this was a specific design decision to not include something like this and if it was, what are the downsides of that?

cc @nnnnnnnn

Not specifically an exclusion! The mutating version is a building block for some of other algorithms, so that's why it was included in the initial release.

1 Like

The non-in-place version is also trivially composable.

edit: unless you want it to be a lazy wrapper I guess.

2 Likes

The lazy version is composable by chaining two slices together:

let c = [10, 20, 30, 40, 50]
let p = 2
let rotated = c[p...].chained(with: c[..<p])

However, a custom Rotated wrapper type can support (1) providing the starting index of the original collection and (2) handling re-rotation without slicing / chaining again.

2 Likes

Thanks for the answers @nnnnnnnn @Ben_Cohen, to me it was more curiosity based on the fact that stdlib defines something like that for reversing a (reverse/reversed) method.

I really like the idea of a custom RotatedCollection wrapper! And since it is also composable, I think we would have nice benefits by having something like it in the library :)

1 Like

I want to make sure that a lazy rotate wrapper is more than just a curiosity—is there a real-world use case where this would have come in handy?

I think not the lazy in fact but an implementation of a rotated method (even with copy) that returns a collection and allows us to chain calls with other functions e.g.

 let c = //... a collection
 c.rotated(by: 2)
  .dropFirst()
  .map(...) ... 

IMO the big advantage of a rotated wrapper, in this case, would be that as still composable, we gain the benefits of O(1) complexity on-call and also, avoiding a copy which can be a positive for large collections.

But as far as a real-world practical use case, TBH I can't think of one ...