about summary refs log tree commit diff
path: root/src/libcore/slice/mod.rs
diff options
context:
space:
mode:
authorCorey Farwell <coreyf@rwell.org>2017-12-16 15:29:09 -0500
committerCorey Farwell <coreyf@rwell.org>2017-12-24 23:01:24 -0800
commit66ef6b9c0995cc678a00f4d061ba8e6adb16f610 (patch)
tree2b53c1439efea0529d62b496929088d5e822114b /src/libcore/slice/mod.rs
parentae65dcc30f421fd91b9e2d67cf77c86bfb20ee3a (diff)
downloadrust-66ef6b9c0995cc678a00f4d061ba8e6adb16f610.tar.gz
rust-66ef6b9c0995cc678a00f4d061ba8e6adb16f610.zip
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.

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/libcore/slice/mod.rs')
-rw-r--r--src/libcore/slice/mod.rs17
1 files changed, 15 insertions, 2 deletions
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index ca5cf04b1d4..fd91227343f 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -201,7 +201,10 @@ pub trait SliceExt {
     fn ends_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq;
 
     #[unstable(feature = "slice_rotate", issue = "41891")]
-    fn rotate(&mut self, mid: usize);
+    fn rotate_left(&mut self, mid: usize);
+
+    #[unstable(feature = "slice_rotate", issue = "41891")]
+    fn rotate_right(&mut self, k: usize);
 
     #[stable(feature = "clone_from_slice", since = "1.7.0")]
     fn clone_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Clone;
@@ -640,7 +643,7 @@ impl<T> SliceExt for [T] {
         self.binary_search_by(|p| p.cmp(x))
     }
 
-    fn rotate(&mut self, mid: usize) {
+    fn rotate_left(&mut self, mid: usize) {
         assert!(mid <= self.len());
         let k = self.len() - mid;
 
@@ -650,6 +653,16 @@ impl<T> SliceExt for [T] {
         }
     }
 
+    fn rotate_right(&mut self, k: usize) {
+        assert!(k <= self.len());
+        let mid = self.len() - k;
+
+        unsafe {
+            let p = self.as_mut_ptr();
+            rotate::ptr_rotate(mid, p.offset(mid as isize), k);
+        }
+    }
+
     #[inline]
     fn clone_from_slice(&mut self, src: &[T]) where T: Clone {
         assert!(self.len() == src.len(),