std: Add Option.{and,and_then,or,or_else}

This commit is contained in:
Erick Tryzelaar 2013-09-11 09:00:27 -07:00
parent 7380b1ce7f
commit d625d4a598
2 changed files with 83 additions and 10 deletions

View File

@ -635,7 +635,7 @@ impl BigUint {
// Converts this BigUint into an int, unless it would overflow.
pub fn to_int_opt(&self) -> Option<int> {
self.to_uint_opt().chain(|n| {
self.to_uint_opt().and_then(|n| {
// If top bit of uint is set, it's too large to convert to
// int.
if (n >> (2*BigDigit::bits - 1) != 0) {
@ -1221,7 +1221,7 @@ impl BigInt {
match self.sign {
Plus => self.data.to_int_opt(),
Zero => Some(0),
Minus => self.data.to_uint_opt().chain(|n| {
Minus => self.data.to_uint_opt().and_then(|n| {
let m: uint = 1 << (2*BigDigit::bits-1);
if (n > m) {
None

View File

@ -127,22 +127,51 @@ impl<T> Option<T> {
#[inline]
pub fn is_some(&self) -> bool { !self.is_none() }
/// Update an optional value by optionally running its content through a
/// function that returns an option.
/// Returns `None` if the option is `None`, otherwise returns `optb`.
#[inline]
pub fn chain<U>(self, f: &fn(t: T) -> Option<U>) -> Option<U> {
pub fn and(self, optb: Option<T>) -> Option<T> {
match self {
Some(t) => f(t),
None => None
Some(_) => optb,
None => None,
}
}
/// Returns the leftmost Some() value, or None if both are None.
/// Returns `None` if the option is `None`, otherwise calls and returns the
/// value of `f`.
#[inline]
pub fn and_then(self, f: &fn() -> Option<T>) -> Option<T> {
match self {
Some(_) => f(),
None => None,
}
}
/// Returns the option if it contains a value, otherwise returns `optb`.
#[inline]
pub fn or(self, optb: Option<T>) -> Option<T> {
match self {
Some(opta) => Some(opta),
_ => optb
Some(_) => self,
None => optb
}
}
/// Returns the option if it contains a value, otherwise calls and returns the
/// value of `f`.
#[inline]
pub fn or_else(self, f: &fn() -> Option<T>) -> Option<T> {
match self {
Some(_) => self,
None => f(),
}
}
/// Update an optional value by optionally running its content through a
/// function that returns an option.
#[inline]
pub fn chain<U>(self, f: &fn(T) -> Option<U>) -> Option<U> {
match self {
Some(t) => f(t),
None => None
}
}
@ -509,6 +538,50 @@ mod tests {
let _y3 = y.take_unwrap();
}
#[test]
fn test_and() {
let x: Option<int> = Some(1);
assert_eq!(x.and(Some(2)), Some(2));
assert_eq!(x.and(None), None);
let x: Option<int> = None;
assert_eq!(x.and(Some(2)), None);
assert_eq!(x.and(None), None);
}
#[test]
fn test_and_then() {
let x: Option<int> = Some(1);
assert_eq!(x.and_then(|| Some(2)), Some(2));
assert_eq!(x.and_then(|| None), None);
let x: Option<int> = None;
assert_eq!(x.and_then(|| Some(2)), None);
assert_eq!(x.and_then(|| None), None);
}
#[test]
fn test_or() {
let x: Option<int> = Some(1);
assert_eq!(x.or(Some(2)), Some(1));
assert_eq!(x.or(None), Some(1));
let x: Option<int> = None;
assert_eq!(x.or(Some(2)), Some(2));
assert_eq!(x.or(None), None);
}
#[test]
fn test_or_else() {
let x: Option<int> = Some(1);
assert_eq!(x.or_else(|| Some(2)), Some(1));
assert_eq!(x.or_else(|| None), Some(1));
let x: Option<int> = None;
assert_eq!(x.or_else(|| Some(2)), Some(2));
assert_eq!(x.or_else(|| None), None);
}
#[test]
fn test_option_while_some() {
let mut i = 0;