How to create a Vec from a range and shuffle it?

I have the following code:

extern crate rand; use rand::{thread_rng, Rng}; fn main() { let mut vec: Vec<u32> = (0..10).collect(); let mut slice: &[u32] = vec.as_mut_slice(); thread_rng().shuffle(slice); } 

and get the following error:

 error[E0308]: mismatched types --> src/main.rs:9:26 | 9 | thread_rng().shuffle(slice); | ^^^^^ types differ in mutability | = note: expected type '&mut [_]' found type '&[u32]' 

I think I understand that the content of vectors and slices is unchanged, and this causes an error here, but I'm not sure.

The signature of as_mut_slice is pub fn as_mut_slice<'a>(&'a mut self) β†’ &'a mut [T] , so the slice must be mutable, but somehow it is not.

I know this should be easy to fix, but I tried my best and could not get it to work.

+14
iterator immutability rust mutability
source share
2 answers

You are very close. This should work:

 extern crate rand; use rand::{thread_rng, Rng}; fn main() { let mut vec: Vec<u32> = (0..10).collect(); let slice: &mut [u32] = &mut vec; thread_rng().shuffle(slice); } 

&mut [T] implicitly forced for &[T] , and you &[u32] slice variable with &[u32] , so the slice has become unchanged: &mut [u32] been cast to &[u32] . mut does not matter for the variable here, because slices simply borrow data belonging to someone else, so they do not inherit variability - their variability is encoded in their types.

In fact, you don't need slice annotation at all. This also works:

 extern crate rand; use rand::{thread_rng, Rng}; fn main() { let mut vec: Vec<u32> = (0..10).collect(); let slice = vec.as_mut_slice(); thread_rng().shuffle(slice); } 

You don't even need an intermediate variable:

 extern crate rand; use rand::{thread_rng, Rng}; fn main() { let mut vec: Vec<u32> = (0..10).collect(); thread_rng().shuffle(&mut vec); } 

You should read The Rust Programming Language as it explains the concepts of ownership and borrowing and how they interact with variability.


Update: Starting with rand v0.6.0, the Rng::shuffle method has been deprecated. Instead, use the rand::seq::SliceRandom . It provides a shuffle() method for all slices that an Rng instance accepts:

 // Rust edition 2018 no longer needs extern crate use rand::thread_rng; use rand::seq::SliceRandom; fn main() { let mut vec: Vec<u32> = (0..10).collect(); vec.shuffle(&mut thread_rng()); println!("{:?}", vec); } 

Watch it on the playground .

+20
source share

You can use shuffle as follows:

 extern crate rand; use rand::Rng; fn main() { let mut vec: Vec<usize> = (0..10).collect(); println!("{:?}", vec); rand::thread_rng().shuffle(&mut vec); println!("{:?}", vec); } 
+14
source share

All Articles