add `insert` and `insert_with` to `Option`

This removes a cause of `unwrap` and code complexity.

This allows replacing

```
option_value = Some(build());
option_value.as_mut().unwrap()
```

with

```
option_value.insert(build())
```

or

```
option_value.insert_with(build)
```

It's also useful in contexts not requiring the mutability of the reference.

Here's a typical cache example:

```
let checked_cache = cache.as_ref().filter(|e| e.is_valid());
let content = match checked_cache {
	Some(e) => &e.content,
	None => {
	    cache = Some(compute_cache_entry());
	    // unwrap is OK because we just filled the option
	    &cache.as_ref().unwrap().content
	}
};
```

It can be changed into

```
let checked_cache = cache.as_ref().filter(|e| e.is_valid());
let content = match checked_cache {
	Some(e) => &e.content,
	None => &cache.insert_with(compute_cache_entry).content,
};
```
This commit is contained in:
Canop 2020-10-01 11:13:38 +02:00
parent a9cd294cf2
commit 9b90e1762e
1 changed files with 46 additions and 0 deletions

View File

@ -562,6 +562,52 @@ impl<T> Option<T> {
}
}
/////////////////////////////////////////////////////////////////////////
// Setting a new value
/////////////////////////////////////////////////////////////////////////
/// Inserts `v` into the option then returns a mutable reference
/// to the contained value.
///
/// # Example
///
/// ```
/// #![feature(option_insert)]
///
/// let mut o = None;
/// let v = o.insert(3);
/// assert_eq!(*v, 3);
/// ```
#[inline]
#[unstable(feature = "option_insert", reason = "new API", issue = "none")]
pub fn insert(&mut self, v: T) -> &mut T {
self.insert_with(|| v)
}
/// Inserts a value computed from `f` into the option, then returns a
/// mutable reference to the contained value.
///
/// # Example
///
/// ```
/// #![feature(option_insert)]
///
/// let mut o = None;
/// let v = o.insert_with(|| 3);
/// assert_eq!(*v, 3);
/// ```
#[inline]
#[unstable(feature = "option_insert", reason = "new API", issue = "none")]
pub fn insert_with<F: FnOnce() -> T>(&mut self, f: F) -> &mut T {
*self = Some(f());
match *self {
Some(ref mut v) => v,
// SAFETY: the code above just filled the option
None => unsafe { hint::unreachable_unchecked() },
}
}
/////////////////////////////////////////////////////////////////////////
// Iterator constructors
/////////////////////////////////////////////////////////////////////////