add Option::{zip,zip_with}
methods under "option_zip" gate
This commit introduces 2 methods - `Option::zip` and `Option::zip_with` with respective signatures: - zip: `(Option<T>, Option<U>) -> Option<(T, U)>` - zip_with: `(Option<T>, Option<U>, (T, U) -> R) -> Option<R>` Both are under the feature gate "option_zip". I'm not sure about the name "zip", maybe we can find a better name for this. (I would prefer `union` for example, but this is a keyword :( ) -------------------------------------------------------------------------------- Recently in a russian rust begginers telegram chat a newbie asked (translated): > Are there any methods for these conversions: > > 1. `(Option<A>, Option<B>) -> Option<(A, B)>` > 2. `Vec<Option<T>> -> Option<Vec<T>>` > > ? While second (2.) is clearly `vec.into_iter().collect::<Option<Vec<_>>()`, the first one isn't that clear. I couldn't find anything similar in the `core` and I've come to this solution: ```rust let tuple: (Option<A>, Option<B>) = ...; let res: Option<(A, B)> = tuple.0.and_then(|a| tuple.1.map(|b| (a, b))); ``` However this solution isn't "nice" (same for just `match`/`if let`), so I thought that this functionality should be in `core`.
This commit is contained in:
parent
d939f708d9
commit
a5206f9749
@ -140,6 +140,7 @@
|
|||||||
#![feature(associated_type_bounds)]
|
#![feature(associated_type_bounds)]
|
||||||
#![feature(const_type_id)]
|
#![feature(const_type_id)]
|
||||||
#![feature(const_caller_location)]
|
#![feature(const_caller_location)]
|
||||||
|
#![feature(option_zip)]
|
||||||
#![feature(no_niche)] // rust-lang/rust#68303
|
#![feature(no_niche)] // rust-lang/rust#68303
|
||||||
|
|
||||||
#[prelude_import]
|
#[prelude_import]
|
||||||
|
@ -913,6 +913,65 @@ impl<T> Option<T> {
|
|||||||
pub fn replace(&mut self, value: T) -> Option<T> {
|
pub fn replace(&mut self, value: T) -> Option<T> {
|
||||||
mem::replace(self, Some(value))
|
mem::replace(self, Some(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Zips `self` with another `Option`.
|
||||||
|
///
|
||||||
|
/// Returns `Some((_, _))` when both `self` and `other`
|
||||||
|
/// are `Some(_)`, otherwise return `None`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(option_zip)]
|
||||||
|
/// let x = Some(1);
|
||||||
|
/// let y = Some("hi");
|
||||||
|
/// let z = None::<u8>;
|
||||||
|
///
|
||||||
|
/// assert_eq!(x.zip(y), Some((1, "hi")));
|
||||||
|
/// assert_eq!(x.zip(z), None);
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "option_zip", issue = "none")]
|
||||||
|
pub fn zip<U>(self, other: Option<U>) -> Option<(T, U)> {
|
||||||
|
self.zip_with(other, |a, b| (a, b))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Zips `self` and another `Option` with function `f`.
|
||||||
|
///
|
||||||
|
/// Returns `Some(_)` when both `self` and `other`
|
||||||
|
/// are `Some(_)`, otherwise return `None`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(option_zip)]
|
||||||
|
///
|
||||||
|
/// #[derive(Debug, PartialEq)]
|
||||||
|
/// struct Point {
|
||||||
|
/// x: f64,
|
||||||
|
/// y: f64,
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// impl Point {
|
||||||
|
/// fn new(x: f64, y: f64) -> Self {
|
||||||
|
/// Self { x, y }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// let x = Some(17.);
|
||||||
|
/// let y = Some(42.);
|
||||||
|
///
|
||||||
|
/// assert_eq!(x.zip_with(y, Point::new), Some(Point { x: 17., y: 42. }));
|
||||||
|
/// assert_eq!(x.zip_with(None, Point::new), None);
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "option_zip", issue = "none")]
|
||||||
|
pub fn zip_with<U, F, R>(self, other: Option<U>, f: F) -> Option<R>
|
||||||
|
where
|
||||||
|
F: FnOnce(T, U) -> R,
|
||||||
|
{
|
||||||
|
Some(f(self?, other?))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Copy> Option<&T> {
|
impl<T: Copy> Option<&T> {
|
||||||
|
Loading…
Reference in New Issue
Block a user