Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When does `vec!` create different elements, or not?

Tags:

rust

I just came across the following code in Rust:

use std::collections::HashMap;
use std::sync::{Arc, Mutex};

fn main() {
    let mut v1 = vec![HashMap::<i32, i32>::new(); 2];
    v1[0].insert(0,0);
    v1[1].insert(1,1);
    println!("{:?}", v1);
    
    let v2 = vec![Arc::new(Mutex::new(HashMap::<i32, i32>::new())); 2];
    v2[0].lock().unwrap().insert(0,0);
    v2[1].lock().unwrap().insert(1,1);
    println!("{:?}", v2);
}

// outputs:
// [{0: 0}, {1: 1}]
// [Mutex { data: {0: 0, 1: 1} }, Mutex { data: {0: 0, 1: 1} }]

link to rust playground

It's apparently v1 has 2 different HashMaps, while v2 has only one. How's that happened? Shouldn't v2 evaluates Arc::new(Mutex::new(HashMap::<i32, i32>::new())) twice (like v1 do) and thus create two different elements? Is it some kind of "lazy" evaluation somewhere?

Pardon my rust newbie question, thanks in advance!

like image 493
bayinamy Avatar asked Dec 13 '22 07:12

bayinamy


2 Answers

The vec![value; n] syntax uses Clone to duplicate the value and fill up the vector. The docs even mention this kind of scenario:

This will use clone to duplicate an expression, so one should be careful using this with types having a nonstandard Clone implementation. For example, vec![Rc::new(1); 5] will create a vector of five references to the same boxed integer value, not five references pointing to independently boxed integers.

like image 96
kmdreko Avatar answered Dec 29 '22 12:12

kmdreko


The vec! macro clones value of the provided expression to fill the vector up to the requested length.

An Arc is a reference-counted smart pointer, which is shared by cloning. Each time you clone an Arc, it increases the reference count to the underlying data, but the underlying data is still the same.

So that's what is happening in your example. The elements of the vector are different pointers to the same HashMap.

like image 34
Peter Hall Avatar answered Dec 29 '22 13:12

Peter Hall