diff options
| author | Corey Farwell <coreyf@rwell.org> | 2018-01-09 22:28:23 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-01-09 22:28:23 -0500 |
| commit | e2e8cd3d14f05c1362b11c2f7ae3561ce585bbc7 (patch) | |
| tree | ee4434e502c1f4304e05477edb55d9aa7a0fdbac /src/liballoc/slice.rs | |
| parent | 2b61564f263edd49fa33f34c8acbc79a55959b8c (diff) | |
| parent | 66ef6b9c0995cc678a00f4d061ba8e6adb16f610 (diff) | |
| download | rust-e2e8cd3d14f05c1362b11c2f7ae3561ce585bbc7.tar.gz rust-e2e8cd3d14f05c1362b11c2f7ae3561ce585bbc7.zip | |
Rollup merge of #46777 - frewsxcv:frewsxcv-rotate, r=alexcrichton
Deprecate [T]::rotate in favor of [T]::rotate_{left,right}.
Background
==========
Slices currently have an **unstable** [`rotate`] method which rotates
elements in the slice to the _left_ N positions. [Here][tracking] is the
tracking issue for this unstable feature.
```rust
let mut a = ['a', 'b' ,'c', 'd', 'e', 'f'];
a.rotate(2);
assert_eq!(a, ['c', 'd', 'e', 'f', 'a', 'b']);
```
Proposal
========
Deprecate the [`rotate`] method and introduce `rotate_left` and
`rotate_right` methods.
```rust
let mut a = ['a', 'b' ,'c', 'd', 'e', 'f'];
a.rotate_left(2);
assert_eq!(a, ['c', 'd', 'e', 'f', 'a', 'b']);
```
```rust
let mut a = ['a', 'b' ,'c', 'd', 'e', 'f'];
a.rotate_right(2);
assert_eq!(a, ['e', 'f', 'a', 'b', 'c', 'd']);
```
Justification
=============
I used this method today for my first time and (probably because I’m a
naive westerner who reads LTR) was surprised when the docs mentioned that
elements get rotated in a left-ward direction. I was in a situation
where I needed to shift elements in a right-ward direction and had to
context switch from the main problem I was working on and think how much
to rotate left in order to accomplish the right-ward rotation I needed.
Ruby’s `Array.rotate` shifts left-ward, Python’s `deque.rotate` shifts
right-ward. Both of their implementations allow passing negative numbers
to shift in the opposite direction respectively. The current `rotate`
implementation takes an unsigned integer argument which doesn't allow
the negative number behavior.
Introducing `rotate_left` and `rotate_right` would:
- remove ambiguity about direction (alleviating need to read docs 😉)
- make it easier for people who need to rotate right
[`rotate`]: https://doc.rust-lang.org/std/primitive.slice.html#method.rotate
[tracking]: https://github.com/rust-lang/rust/issues/41891
Diffstat (limited to 'src/liballoc/slice.rs')
| -rw-r--r-- | src/liballoc/slice.rs | 99 |
1 files changed, 64 insertions, 35 deletions
diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index fa73197885b..28caccbc87f 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -1360,24 +1360,61 @@ impl<T> [T] { core_slice::SliceExt::sort_unstable_by_key(self, f); } - /// Permutes the slice in-place such that `self[mid..]` moves to the - /// beginning of the slice while `self[..mid]` moves to the end of the - /// slice. Equivalently, rotates the slice `mid` places to the left - /// or `k = self.len() - mid` places to the right. + /// Rotates the slice in-place such that the first `mid` elements of the + /// slice move to the end while the last `self.len() - mid` elements move to + /// the front. After calling `rotate_left`, the element previously at index + /// `mid` will become the first element in the slice. /// - /// This is a "k-rotation", a permutation in which item `i` moves to - /// position `i + k`, modulo the length of the slice. See _Elements - /// of Programming_ [§10.4][eop]. + /// # Panics + /// + /// This function will panic if `mid` is greater than the length of the + /// slice. Note that `mid == self.len()` does _not_ panic and is a no-op + /// rotation. + /// + /// # Complexity + /// + /// Takes linear (in `self.len()`) time. + /// + /// # Examples /// - /// Rotation by `mid` and rotation by `k` are inverse operations. + /// ``` + /// #![feature(slice_rotate)] /// - /// [eop]: https://books.google.com/books?id=CO9ULZGINlsC&pg=PA178&q=k-rotation + /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f']; + /// a.rotate_left(2); + /// assert_eq!(a, ['c', 'd', 'e', 'f', 'a', 'b']); + /// ``` + /// + /// Rotating a subslice: + /// + /// ``` + /// #![feature(slice_rotate)] + /// + /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f']; + /// a[1..5].rotate_left(1); + /// assert_eq!(a, ['a', 'c', 'd', 'e', 'b', 'f']); + /// ``` + #[unstable(feature = "slice_rotate", issue = "41891")] + pub fn rotate_left(&mut self, mid: usize) { + core_slice::SliceExt::rotate_left(self, mid); + } + + #[unstable(feature = "slice_rotate", issue = "41891")] + #[rustc_deprecated(since = "", reason = "renamed to `rotate_left`")] + pub fn rotate(&mut self, mid: usize) { + core_slice::SliceExt::rotate_left(self, mid); + } + + /// Rotates the slice in-place such that the first `self.len() - k` + /// elements of the slice move to the end while the last `k` elements move + /// to the front. After calling `rotate_right`, the element previously at + /// index `self.len() - k` will become the first element in the slice. /// /// # Panics /// - /// This function will panic if `mid` is greater than the length of the - /// slice. (Note that `mid == self.len()` does _not_ panic; it's a nop - /// rotation with `k == 0`, the inverse of a rotation with `mid == 0`.) + /// This function will panic if `k` is greater than the length of the + /// slice. Note that `k == self.len()` does _not_ panic and is a no-op + /// rotation. /// /// # Complexity /// @@ -1388,31 +1425,23 @@ impl<T> [T] { /// ``` /// #![feature(slice_rotate)] /// - /// let mut a = [1, 2, 3, 4, 5, 6, 7]; - /// let mid = 2; - /// a.rotate(mid); - /// assert_eq!(&a, &[3, 4, 5, 6, 7, 1, 2]); - /// let k = a.len() - mid; - /// a.rotate(k); - /// assert_eq!(&a, &[1, 2, 3, 4, 5, 6, 7]); - /// - /// use std::ops::Range; - /// fn slide<T>(slice: &mut [T], range: Range<usize>, to: usize) { - /// if to < range.start { - /// slice[to..range.end].rotate(range.start-to); - /// } else if to > range.end { - /// slice[range.start..to].rotate(range.end-range.start); - /// } - /// } - /// let mut v: Vec<_> = (0..10).collect(); - /// slide(&mut v, 1..4, 7); - /// assert_eq!(&v, &[0, 4, 5, 6, 1, 2, 3, 7, 8, 9]); - /// slide(&mut v, 6..8, 1); - /// assert_eq!(&v, &[0, 3, 7, 4, 5, 6, 1, 2, 8, 9]); + /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f']; + /// a.rotate_right(2); + /// assert_eq!(a, ['e', 'f', 'a', 'b', 'c', 'd']); + /// ``` + /// + /// Rotate a subslice: + /// + /// ``` + /// #![feature(slice_rotate)] + /// + /// let mut a = ['a', 'b', 'c', 'd', 'e', 'f']; + /// a[1..5].rotate_right(1); + /// assert_eq!(a, ['a', 'e', 'b', 'c', 'd', 'f']); /// ``` #[unstable(feature = "slice_rotate", issue = "41891")] - pub fn rotate(&mut self, mid: usize) { - core_slice::SliceExt::rotate(self, mid); + pub fn rotate_right(&mut self, k: usize) { + core_slice::SliceExt::rotate_right(self, k); } /// Copies the elements from `src` into `self`. |
