Rollup merge of #49727 - stjepang:cell-update, r=SimonSapin
Add Cell::update This commit adds a new method `Cell::update`, which applies a function to the value inside the cell. Previously discussed in: https://github.com/rust-lang/rfcs/issues/2171 ### Motivation Updating `Cell`s is currently a bit verbose. Here are several real examples (taken from rustc and crossbeam): ```rust self.print_fuel.set(self.print_fuel.get() + 1); self.diverges.set(self.diverges.get() | Diverges::Always); let guard_count = self.guard_count.get(); self.guard_count.set(guard_count.checked_add(1).unwrap()); if guard_count == 0 { // ... } ``` With the addition of the new method `Cell::update`, this code can be simplified to: ```rust self.print_fuel.update(|x| x + 1); self.diverges.update(|x| x | Diverges::Always); if self.guard_count.update(|x| x.checked_add(1).unwrap()) == 1 { // ... } ``` ### Unresolved questions 1. Should we return the old value instead of the new value (like in `fetch_add` and `fetch_update`)? 2. Should the return type simply be `()`? 3. Naming: `update` vs `modify` vs `mutate` etc. cc @SimonSapin
This commit is contained in:
commit
91cc872987
@ -256,6 +256,33 @@ impl<T:Copy> Cell<T> {
|
||||
pub fn get(&self) -> T {
|
||||
unsafe{ *self.value.get() }
|
||||
}
|
||||
|
||||
/// Updates the contained value using a function and returns the new value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(cell_update)]
|
||||
///
|
||||
/// use std::cell::Cell;
|
||||
///
|
||||
/// let c = Cell::new(5);
|
||||
/// let new = c.update(|x| x + 1);
|
||||
///
|
||||
/// assert_eq!(new, 6);
|
||||
/// assert_eq!(c.get(), 6);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "cell_update", issue = "50186")]
|
||||
pub fn update<F>(&self, f: F) -> T
|
||||
where
|
||||
F: FnOnce(T) -> T,
|
||||
{
|
||||
let old = self.get();
|
||||
let new = f(old);
|
||||
self.set(new);
|
||||
new
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -26,6 +26,17 @@ fn smoketest_cell() {
|
||||
assert!(y.get() == (30, 40));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cell_update() {
|
||||
let x = Cell::new(10);
|
||||
|
||||
assert_eq!(x.update(|x| x + 5), 15);
|
||||
assert_eq!(x.get(), 15);
|
||||
|
||||
assert_eq!(x.update(|x| x / 3), 5);
|
||||
assert_eq!(x.get(), 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cell_has_sensible_show() {
|
||||
let x = Cell::new("foo bar");
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#![feature(ascii_ctype)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(cell_update)]
|
||||
#![feature(core_float)]
|
||||
#![feature(core_private_bignum)]
|
||||
#![feature(core_private_diy_float)]
|
||||
|
Loading…
Reference in New Issue
Block a user