diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index c8ee166fee3..2ea1b84d034 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -256,6 +256,30 @@ impl Cell { pub fn get(&self) -> T { unsafe{ *self.value.get() } } + + /// Applies a function to the contained value. + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// c.update(|x| x + 1); + /// + /// assert_eq!(c.get(), 6); + /// ``` + #[inline] + #[unstable(feature = "cell_update", issue = "0")] // TODO: issue + pub fn update(&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")] diff --git a/src/libcore/tests/cell.rs b/src/libcore/tests/cell.rs index cc0ef6a6f17..962fb2f0e02 100644 --- a/src/libcore/tests/cell.rs +++ b/src/libcore/tests/cell.rs @@ -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");