Skip to content

slice::rotate_left

slice methods · Collections

Level: reference · for working programmers

One line: Shift every element mid places left, wrapping the first mid around to the end.

pub const fn rotate_left(&mut self, mid: usize)

Stable since 1.26.0; const since 1.92.0.

[1, 2, 3, 4, 5].rotate_left(2) is [3, 4, 5, 1, 2]: the first two go to the back, everything else slides down. In place, O(n), and rotate_right undoes it.

The everyday case is a turn order — rotate_left(1) moves whoever is at the front to the back, in place, where remove(0) + push would shift everything twice.

mid may be anything from 0 to len() inclusive — rotate_left(len) is a no-op — and mid > len panics. It does not wrap, so a rotation by an arbitrary count is rotate_left(k % v.len()), and the % is yours to write (and to guard against an empty slice, where % 0 panics first). Compute it on its own line: r.rotate_left(7 % r.len()) is error[E0502], because the &mut borrow for the call is taken before the len() inside the argument is read — the two-phase borrow that lets v.push(v.len()) through does not reach through the Vec-to-slice deref.

Example

slice_rotate_left.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.

fn main() {
    let mut v = vec![1, 2, 3, 4, 5];
    v.rotate_left(2);
    println!("{v:?}");
    v.rotate_right(2);
    println!("{v:?}  <- rotate_right undoes it");

    // mid == len is a no-op. (Computed first: v.rotate_left(v.len()) is E0502.)
    let n = v.len();
    v.rotate_left(n);
    println!("{v:?}");

    // A turn order: front to back, in place.
    let mut turn = vec!["Ann", "Bob", "Cal"];
    for _ in 0..4 {
        print!("{} ", turn[0]);
        turn.rotate_left(1);
    }
    println!();

    // It does not wrap: rotate by k % len, not by k. The k is computed on
    // its own line: `r.rotate_left(7 % r.len())` is error[E0502], because the
    // &mut borrow for the call starts before the len() read inside the argument.
    let mut r = vec![1, 2, 3];
    let k = 7 % r.len();
    r.rotate_left(k);
    println!("{r:?}");

    // The panic is caught here so the program can report it and go on.
    let hook = std::panic::take_hook();
    std::panic::set_hook(Box::new(|_| {}));
    let r2 = std::panic::catch_unwind(move || r.rotate_left(7));
    std::panic::set_hook(hook);
    println!("rotate_left(7) on 3 elements panicked: {}", r2.is_err());
}

Verified output of slice_rotate_left.rs — regenerated by tools/run_examples.py, never hand-typed.

[3, 4, 5, 1, 2]
[1, 2, 3, 4, 5]  <- rotate_right undoes it
[1, 2, 3, 4, 5]
Ann Bob Cal Ann 
[2, 3, 1]
rotate_left(7) on 3 elements panicked: true

See also

slice::rotate_left in the standard library ↗