about summary refs log tree commit diff
path: root/src/libstd/either.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd/either.rs')
-rw-r--r--src/libstd/either.rs366
1 files changed, 173 insertions, 193 deletions
diff --git a/src/libstd/either.rs b/src/libstd/either.rs
index 6bdc45d7204..cfaef550c6f 100644
--- a/src/libstd/either.rs
+++ b/src/libstd/either.rs
@@ -23,29 +23,102 @@ use str::StrSlice;
 use vec;
 use vec::{OwnedVector, ImmutableVector};
 
-/// The either type
+/// `Either` is a type that represents one of two alternatives
 #[deriving(Clone, Eq)]
-pub enum Either<T, U> {
-    Left(T),
-    Right(U)
+pub enum Either<L, R> {
+    Left(L),
+    Right(R)
 }
 
-/// Applies a function based on the given either value
-///
-/// If `value` is left(T) then `f_left` is applied to its contents, if
-/// `value` is right(U) then `f_right` is applied to its contents, and the
-/// result is returned.
-#[inline]
-pub fn either<T, U, V>(f_left: &fn(&T) -> V,
-                       f_right: &fn(&U) -> V, value: &Either<T, U>) -> V {
-    match *value {
-        Left(ref l) => f_left(l),
-        Right(ref r) => f_right(r)
+impl<L, R> Either<L, R> {
+    /// Applies a function based on the given either value
+    ///
+    /// If `value` is `Left(L)` then `f_left` is applied to its contents, if
+    /// `value` is `Right(R)` then `f_right` is applied to its contents, and the
+    /// result is returned.
+    #[inline]
+    pub fn either<T>(&self, f_left: &fn(&L) -> T, f_right: &fn(&R) -> T) -> T {
+        match *self {
+            Left(ref l) => f_left(l),
+            Right(ref r) => f_right(r)
+        }
+    }
+
+    /// Flips between left and right of a given `Either`
+    #[inline]
+    pub fn flip(self) -> Either<R, L> {
+        match self {
+            Right(r) => Left(r),
+            Left(l) => Right(l)
+        }
+    }
+
+    /// Converts a `Either` to a `Result`
+    ///
+    /// Converts an `Either` type to a `Result` type, making the "right" choice
+    /// an `Ok` result, and the "left" choice a `Err`
+    #[inline]
+    pub fn to_result(self) -> Result<R, L> {
+        match self {
+            Right(r) => result::Ok(r),
+            Left(l) => result::Err(l)
+        }
+    }
+
+    /// Checks whether the given value is a `Left`
+    #[inline]
+    pub fn is_left(&self) -> bool {
+        match *self {
+            Left(_) => true,
+            _ => false
+        }
+    }
+
+    /// Checks whether the given value is a `Right`
+    #[inline]
+    pub fn is_right(&self) -> bool {
+        match *self {
+            Right(_) => true,
+            _ => false
+        }
+    }
+
+    /// Retrieves the value from a `Left`.
+    /// Fails with a specified reason if the `Either` is `Right`.
+    #[inline]
+    pub fn expect_left(self, reason: &str) -> L {
+        match self {
+            Left(x) => x,
+            Right(_) => fail!(reason.to_owned())
+        }
+    }
+
+    /// Retrieves the value from a `Left`. Fails if the `Either` is `Right`.
+    #[inline]
+    pub fn unwrap_left(self) -> L {
+        self.expect_left("called Either::unwrap_left()` on `Right` value")
+    }
+
+    /// Retrieves the value from a `Right`.
+    /// Fails with a specified reason if the `Either` is `Left`.
+    #[inline]
+    pub fn expect_right(self, reason: &str) -> R {
+        match self {
+            Right(x) => x,
+            Left(_) => fail!(reason.to_owned())
+        }
+    }
+
+    /// Retrieves the value from a `Right`. Fails if the `Either` is `Left`.
+    #[inline]
+    pub fn unwrap_right(self) -> R {
+        self.expect_right("called Either::unwrap_right()` on `Left` value")
     }
 }
 
+// FIXME: #8228 Replaceable by an external iterator?
 /// Extracts from a vector of either all the left values
-pub fn lefts<T:Clone,U>(eithers: &[Either<T, U>]) -> ~[T] {
+pub fn lefts<L: Clone, R>(eithers: &[Either<L, R>]) -> ~[L] {
     do vec::build_sized(eithers.len()) |push| {
         for elt in eithers.iter() {
             match *elt {
@@ -56,8 +129,9 @@ pub fn lefts<T:Clone,U>(eithers: &[Either<T, U>]) -> ~[T] {
     }
 }
 
+// FIXME: #8228 Replaceable by an external iterator?
 /// Extracts from a vector of either all the right values
-pub fn rights<T, U: Clone>(eithers: &[Either<T, U>]) -> ~[U] {
+pub fn rights<L, R: Clone>(eithers: &[Either<L, R>]) -> ~[R] {
     do vec::build_sized(eithers.len()) |push| {
         for elt in eithers.iter() {
             match *elt {
@@ -68,13 +142,14 @@ pub fn rights<T, U: Clone>(eithers: &[Either<T, U>]) -> ~[U] {
     }
 }
 
+// FIXME: #8228 Replaceable by an external iterator?
 /// Extracts from a vector of either all the left values and right values
 ///
 /// Returns a structure containing a vector of left values and a vector of
 /// right values.
-pub fn partition<T, U>(eithers: ~[Either<T, U>]) -> (~[T], ~[U]) {
-    let mut lefts: ~[T] = ~[];
-    let mut rights: ~[U] = ~[];
+pub fn partition<L, R>(eithers: ~[Either<L, R>]) -> (~[L], ~[R]) {
+    let mut lefts: ~[L] = ~[];
+    let mut rights: ~[R] = ~[];
     for elt in eithers.consume_iter() {
         match elt {
             Left(l) => lefts.push(l),
@@ -84,196 +159,101 @@ pub fn partition<T, U>(eithers: ~[Either<T, U>]) -> (~[T], ~[U]) {
     return (lefts, rights);
 }
 
-/// Flips between left and right of a given either
-#[inline]
-pub fn flip<T, U>(eith: Either<T, U>) -> Either<U, T> {
-    match eith {
-        Right(r) => Left(r),
-        Left(l) => Right(l)
-    }
-}
+#[cfg(test)]
+mod tests {
+    use super::*;
 
-/// Converts either::t to a result::t
-///
-/// Converts an `either` type to a `result` type, making the "right" choice
-/// an ok result, and the "left" choice a fail
-#[inline]
-pub fn to_result<T, U>(eith: Either<T, U>) -> Result<U, T> {
-    match eith {
-        Right(r) => result::Ok(r),
-        Left(l) => result::Err(l)
+    #[test]
+    fn test_either_left() {
+        let val = Left(10);
+        fn f_left(x: &int) -> bool { *x == 10 }
+        fn f_right(_x: &uint) -> bool { false }
+        assert!(val.either(f_left, f_right));
     }
-}
 
-/// Checks whether the given value is a left
-#[inline]
-pub fn is_left<T, U>(eith: &Either<T, U>) -> bool {
-    match *eith {
-        Left(_) => true,
-        _ => false
+    #[test]
+    fn test_either_right() {
+        let val = Right(10u);
+        fn f_left(_x: &int) -> bool { false }
+        fn f_right(x: &uint) -> bool { *x == 10u }
+        assert!(val.either(f_left, f_right));
     }
-}
 
-/// Checks whether the given value is a right
-#[inline]
-pub fn is_right<T, U>(eith: &Either<T, U>) -> bool {
-    match *eith {
-        Right(_) => true,
-        _ => false
+    #[test]
+    fn test_lefts() {
+        let input = ~[Left(10), Right(11), Left(12), Right(13), Left(14)];
+        let result = lefts(input);
+        assert_eq!(result, ~[10, 12, 14]);
     }
-}
 
-/// Retrieves the value in the left branch.
-/// Fails with a specified reason if the either is Right.
-#[inline]
-pub fn expect_left<T,U>(eith: Either<T,U>, reason: &str) -> T {
-    match eith {
-        Left(x) => x,
-        Right(_) => fail!(reason.to_owned())
+    #[test]
+    fn test_lefts_none() {
+        let input: ~[Either<int, int>] = ~[Right(10), Right(10)];
+        let result = lefts(input);
+        assert_eq!(result.len(), 0u);
     }
-}
 
-/// Retrieves the value in the left branch. Fails if the either is Right.
-#[inline]
-pub fn unwrap_left<T,U>(eith: Either<T,U>) -> T {
-    expect_left(eith, "either::unwrap_left Right")
-}
-
-/// Retrieves the value in the right branch.
-/// Fails with a specified reason if the either is Left.
-#[inline]
-pub fn expect_right<T,U>(eith: Either<T,U>, reason: &str) -> U {
-    match eith {
-        Right(x) => x,
-        Left(_) => fail!(reason.to_owned())
+    #[test]
+    fn test_lefts_empty() {
+        let input: ~[Either<int, int>] = ~[];
+        let result = lefts(input);
+        assert_eq!(result.len(), 0u);
     }
-}
 
-/// Retrieves the value in the right branch. Fails if the either is Left.
-pub fn unwrap_right<T,U>(eith: Either<T,U>) -> U {
-    expect_right(eith, "either::unwrap_right Left")
-}
-
-impl<T, U> Either<T, U> {
-    #[inline]
-    pub fn either<V>(&self, f_left: &fn(&T) -> V, f_right: &fn(&U) -> V) -> V {
-        either(f_left, f_right, self)
+    #[test]
+    fn test_rights() {
+        let input = ~[Left(10), Right(11), Left(12), Right(13), Left(14)];
+        let result = rights(input);
+        assert_eq!(result, ~[11, 13]);
     }
 
-    #[inline]
-    pub fn flip(self) -> Either<U, T> { flip(self) }
-
-    #[inline]
-    pub fn to_result(self) -> Result<U, T> { to_result(self) }
-
-    #[inline]
-    pub fn is_left(&self) -> bool { is_left(self) }
-
-    #[inline]
-    pub fn is_right(&self) -> bool { is_right(self) }
-
-    #[inline]
-    pub fn expect_left(self, reason: &str) -> T { expect_left(self, reason) }
-
-    #[inline]
-    pub fn unwrap_left(self) -> T { unwrap_left(self) }
-
-    #[inline]
-    pub fn expect_right(self, reason: &str) -> U { expect_right(self, reason) }
-
-    #[inline]
-    pub fn unwrap_right(self) -> U { unwrap_right(self) }
-}
-
-#[test]
-fn test_either_left() {
-    let val = Left(10);
-    fn f_left(x: &int) -> bool { *x == 10 }
-    fn f_right(_x: &uint) -> bool { false }
-    assert!((either(f_left, f_right, &val)));
-}
-
-#[test]
-fn test_either_right() {
-    let val = Right(10u);
-    fn f_left(_x: &int) -> bool { false }
-    fn f_right(x: &uint) -> bool { *x == 10u }
-    assert!((either(f_left, f_right, &val)));
-}
-
-#[test]
-fn test_lefts() {
-    let input = ~[Left(10), Right(11), Left(12), Right(13), Left(14)];
-    let result = lefts(input);
-    assert_eq!(result, ~[10, 12, 14]);
-}
-
-#[test]
-fn test_lefts_none() {
-    let input: ~[Either<int, int>] = ~[Right(10), Right(10)];
-    let result = lefts(input);
-    assert_eq!(result.len(), 0u);
-}
-
-#[test]
-fn test_lefts_empty() {
-    let input: ~[Either<int, int>] = ~[];
-    let result = lefts(input);
-    assert_eq!(result.len(), 0u);
-}
-
-#[test]
-fn test_rights() {
-    let input = ~[Left(10), Right(11), Left(12), Right(13), Left(14)];
-    let result = rights(input);
-    assert_eq!(result, ~[11, 13]);
-}
+    #[test]
+    fn test_rights_none() {
+        let input: ~[Either<int, int>] = ~[Left(10), Left(10)];
+        let result = rights(input);
+        assert_eq!(result.len(), 0u);
+    }
 
-#[test]
-fn test_rights_none() {
-    let input: ~[Either<int, int>] = ~[Left(10), Left(10)];
-    let result = rights(input);
-    assert_eq!(result.len(), 0u);
-}
+    #[test]
+    fn test_rights_empty() {
+        let input: ~[Either<int, int>] = ~[];
+        let result = rights(input);
+        assert_eq!(result.len(), 0u);
+    }
 
-#[test]
-fn test_rights_empty() {
-    let input: ~[Either<int, int>] = ~[];
-    let result = rights(input);
-    assert_eq!(result.len(), 0u);
-}
+    #[test]
+    fn test_partition() {
+        let input = ~[Left(10), Right(11), Left(12), Right(13), Left(14)];
+        let (lefts, rights) = partition(input);
+        assert_eq!(lefts[0], 10);
+        assert_eq!(lefts[1], 12);
+        assert_eq!(lefts[2], 14);
+        assert_eq!(rights[0], 11);
+        assert_eq!(rights[1], 13);
+    }
 
-#[test]
-fn test_partition() {
-    let input = ~[Left(10), Right(11), Left(12), Right(13), Left(14)];
-    let (lefts, rights) = partition(input);
-    assert_eq!(lefts[0], 10);
-    assert_eq!(lefts[1], 12);
-    assert_eq!(lefts[2], 14);
-    assert_eq!(rights[0], 11);
-    assert_eq!(rights[1], 13);
-}
+    #[test]
+    fn test_partition_no_lefts() {
+        let input: ~[Either<int, int>] = ~[Right(10), Right(11)];
+        let (lefts, rights) = partition(input);
+        assert_eq!(lefts.len(), 0u);
+        assert_eq!(rights.len(), 2u);
+    }
 
-#[test]
-fn test_partition_no_lefts() {
-    let input: ~[Either<int, int>] = ~[Right(10), Right(11)];
-    let (lefts, rights) = partition(input);
-    assert_eq!(lefts.len(), 0u);
-    assert_eq!(rights.len(), 2u);
-}
+    #[test]
+    fn test_partition_no_rights() {
+        let input: ~[Either<int, int>] = ~[Left(10), Left(11)];
+        let (lefts, rights) = partition(input);
+        assert_eq!(lefts.len(), 2u);
+        assert_eq!(rights.len(), 0u);
+    }
 
-#[test]
-fn test_partition_no_rights() {
-    let input: ~[Either<int, int>] = ~[Left(10), Left(11)];
-    let (lefts, rights) = partition(input);
-    assert_eq!(lefts.len(), 2u);
-    assert_eq!(rights.len(), 0u);
-}
+    #[test]
+    fn test_partition_empty() {
+        let input: ~[Either<int, int>] = ~[];
+        let (lefts, rights) = partition(input);
+        assert_eq!(lefts.len(), 0u);
+        assert_eq!(rights.len(), 0u);
+    }
 
-#[test]
-fn test_partition_empty() {
-    let input: ~[Either<int, int>] = ~[];
-    let (lefts, rights) = partition(input);
-    assert_eq!(lefts.len(), 0u);
-    assert_eq!(rights.len(), 0u);
 }