Cells

Let's start with the basic Cell structure. A Cell will contain a mutable value, but it can be mutated without having a mutable Cell. It has mainly three interesting methods: set(), swap(), and replace(). The first allows us to set the contained value, replacing it with a new value. The previous structure will be dropped (the destructor will run). That last bit is the only difference with the replace() method. In the replace() method, instead of dropping the previous value, it will be returned. The swap() method, on the other hand, will take another Cell and swap the values between the two. All this without the Cell needing to be mutable. Let's see it with an example:

use std::cell::Cell;

#[derive(Copy, Clone)]
struct House {
bedrooms: u8,
}

impl Default for House {
fn default() -> Self {
House { bedrooms: 1 }
}
}

fn main() {
let my_house = House { bedrooms: 2 };
let my_dream_house = House { bedrooms: 5 };

let my_cell = Cell::new(my_house);
println!("My house has {} bedrooms.", my_cell.get().bedrooms);

my_cell.set(my_dream_house);
println!("My new house has {} bedrooms.", my_cell.get().bedrooms);

let my_new_old_house = my_cell.replace(my_house);
println!(
"My house has {} bedrooms, it was better with {}",
my_cell.get().bedrooms,
my_new_old_house.bedrooms
);

let my_new_cell = Cell::new(my_dream_house);

my_cell.swap(&my_new_cell);
println!(
"Yay! my current house has {} bedrooms! (my new house {})",
my_cell.get().bedrooms,
my_new_cell.get().bedrooms
);

let my_final_house = my_cell.take();
println!(
"My final house has {} bedrooms, the shared one {}",
my_final_house.bedrooms,
my_cell.get().bedrooms
);
}

As you can see in the example, to use a Cell, the contained type must be Copy. If the contained type is not Copy, you will need to use a RefCell, which we will see next. Continuing with this Cell example, as you can see through the code, the output will be the following:

So we first create two houses, we select one of them as the current one, and we keep mutating the current and the new ones. As you might have seen, I also used the take() method, only available for types implementing the Default trait. This method will return the current value, replacing it with the default value. As you can see, you don't really mutate the value inside, but you replace it with another value. You can either retrieve the old value or lose it. Also, when using the get() method, you get a copy of the current value, and not a reference to it. That's why you can only use elements implementing Copy with a Cell. This also means that a Cell does not need to dynamically check borrows at runtime.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.58.51.36