Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I 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 immutable and that causes the error here, but I'm unsure.

The signature of as_mut_slice is pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T], so the slice should be mutable, but it somehow isn't.

I know that there must be an easy fix, but I tried my best and couldn't get it to work.

like image 989
le_me Avatar asked Sep 25 '14 08:09

le_me


2 Answers

Rand v0.6.0

The Rng::shuffle method is now deprecated; rand::seq::SliceRandom trait should be used. It provides the shuffle() method on all slices, which accepts an Rng instance:

// 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); } 

See it on Playground.

Original answer

You're 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] is implicitly coercible to &[T], and you annotated the slice variable with &[u32], so the slice became immutable: &mut [u32] was coerced to &[u32]. mut on the variable is not relevant here because slices are just borrows into data owned by someone else, so they do not have inherited mutability - their mutability is encoded in their types.

In fact, you don't need an annotation on slice at all. This works as well:

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 the 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 mutability.


like image 136
Vladimir Matveev Avatar answered Oct 02 '22 07:10

Vladimir Matveev


You can use shuffle like this:

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);
}
like image 42
Akavall Avatar answered Oct 02 '22 06:10

Akavall