diff options
| author | Marvin Löbel <loebel.marvin@gmail.com> | 2013-10-31 23:09:24 +0100 |
|---|---|---|
| committer | Marvin Löbel <loebel.marvin@gmail.com> | 2013-11-01 15:00:46 +0100 |
| commit | 0d92c53f4a5707ee994d74d9e96995d7bac2ab13 (patch) | |
| tree | 4ecff877b97d43c3f1ce5666cbd6a9630648eb8c /src/libstd/result.rs | |
| parent | 04c58c9f81c5d9b6b1847573a41c8b819893a12a (diff) | |
| download | rust-0d92c53f4a5707ee994d74d9e96995d7bac2ab13.tar.gz rust-0d92c53f4a5707ee994d74d9e96995d7bac2ab13.zip | |
Reordered the methods in std::Option and std::Result
Cleaned up the source in a few places Renamed `map_move` to `map`, removed other `map` methods Added `as_ref` and `as_mut` adapters to `Result` Added `fmt::Default` impl
Diffstat (limited to 'src/libstd/result.rs')
| -rw-r--r-- | src/libstd/result.rs | 323 |
1 files changed, 154 insertions, 169 deletions
diff --git a/src/libstd/result.rs b/src/libstd/result.rs index 957ba4a0438..cf2fa4468e7 100644 --- a/src/libstd/result.rs +++ b/src/libstd/result.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -10,19 +10,18 @@ //! A type representing either success or failure -#[allow(missing_doc)]; - +use any::Any; use clone::Clone; use cmp::Eq; use either; +use fmt; use iter::Iterator; +use kinds::Send; use option::{None, Option, Some, OptionIterator}; use option; -use vec; -use vec::OwnedVector; use to_str::ToStr; -use str::StrSlice; -use fmt; +use vec::OwnedVector; +use vec; /// `Result` is a type that represents either success (`Ok`) or failure (`Err`). /// @@ -37,20 +36,14 @@ pub enum Result<T, E> { Err(E) } +///////////////////////////////////////////////////////////////////////////// +// Type implementation +///////////////////////////////////////////////////////////////////////////// + impl<T, E: ToStr> Result<T, E> { - /// Get a reference to the value out of a successful result - /// - /// # Failure - /// - /// If the result is an error - #[inline] - pub fn get_ref<'a>(&'a self) -> &'a T { - match *self { - Ok(ref t) => t, - Err(ref e) => fail!("called `Result::get_ref()` on `Err` value: {}", - e.to_str()), - } - } + ///////////////////////////////////////////////////////////////////////// + // Querying the contained values + ///////////////////////////////////////////////////////////////////////// /// Returns true if the result is `Ok` #[inline] @@ -67,137 +60,153 @@ impl<T, E: ToStr> Result<T, E> { !self.is_ok() } - /// Call a method based on a previous result - /// - /// If `self` is `Ok` then the value is extracted and passed to `op` - /// whereupon `op`s result is returned. if `self` is `Err` then it is - /// immediately returned. This function can be used to compose the results - /// of two functions. - /// - /// Example: - /// - /// for buf in read_file(file) { - /// print_buf(buf) - /// } + ///////////////////////////////////////////////////////////////////////// + // Adapter for working with references + ///////////////////////////////////////////////////////////////////////// + + /// Convert from `Result<T, E>` to `Result<&T, &E>` #[inline] - pub fn iter<'r>(&'r self) -> OptionIterator<&'r T> { + pub fn as_ref<'r>(&'r self) -> Result<&'r T, &'r E> { match *self { - Ok(ref t) => Some(t), - Err(*) => None, - }.move_iter() + Ok(ref x) => Ok(x), + Err(ref x) => Err(x), + } } - /// Call a method based on a previous result - /// - /// If `self` is `Err` then the value is extracted and passed to `op` - /// whereupon `op`s result is returned. if `self` is `Ok` then it is - /// immediately returned. This function can be used to pass through a - /// successful result while handling an error. + /// Convert from `Result<T, E>` to `Result<&mut T, &mut E>` #[inline] - pub fn iter_err<'r>(&'r self) -> OptionIterator<&'r E> { + pub fn as_mut<'r>(&'r mut self) -> Result<&'r mut T, &'r mut E> { match *self { - Ok(*) => None, - Err(ref t) => Some(t), - }.move_iter() + Ok(ref mut x) => Ok(x), + Err(ref mut x) => Err(x), + } } + ///////////////////////////////////////////////////////////////////////// + // Getting to contained values + ///////////////////////////////////////////////////////////////////////// + /// Unwraps a result, yielding the content of an `Ok`. - /// Fails if the value is a `Err` with an error message derived - /// from `E`'s `ToStr` implementation. + /// Fails if the value is a `Err` with a custom failure message provided by `msg`. #[inline] - pub fn unwrap(self) -> T { + pub fn expect<M: Any + Send>(self, msg: M) -> T { match self { Ok(t) => t, - Err(e) => fail!("called `Result::unwrap()` on `Err` value: {}", - e.to_str()), + Err(_) => fail!(msg), } } /// Unwraps a result, yielding the content of an `Err`. - /// Fails if the value is a `Ok`. + /// Fails if the value is a `Ok` with a custom failure message provided by `msg`. #[inline] - pub fn unwrap_err(self) -> E { - self.expect_err("called `Result::unwrap_err()` on `Ok` value") + pub fn expect_err<M: Any + Send>(self, msg: M) -> E { + match self { + Err(e) => e, + Ok(_) => fail!(msg), + } } /// Unwraps a result, yielding the content of an `Ok`. - /// Fails if the value is a `Err` with a custom failure message. + /// Fails if the value is a `Err` with an error message derived + /// from `E`'s `ToStr` implementation. #[inline] - pub fn expect(self, reason: &str) -> T { + pub fn unwrap(self) -> T { match self { Ok(t) => t, - Err(_) => fail!("{}", reason.to_owned()), + Err(e) => fail!("called `Result::unwrap()` on `Err` value '{}'", + e.to_str()), } } - /// Unwraps a result, yielding the content of an `Err` - /// Fails if the value is a `Ok` with a custom failure message. + /// Unwraps a result, yielding the content of an `Err`. + /// Fails if the value is a `Ok`. #[inline] - pub fn expect_err(self, reason: &str) -> E { + pub fn unwrap_err(self) -> E { match self { - Err(e) => e, - Ok(_) => fail!("{}", reason.to_owned()), + Ok(_) => fail!("called `Result::unwrap_err()` on an `Ok` value"), + Err(e) => e } } - /// Call a method based on a previous result + ///////////////////////////////////////////////////////////////////////// + // Transforming contained values + ///////////////////////////////////////////////////////////////////////// + + /// Maps an `Result<T, E>` to `Result<U, E>` by applying a function to an + /// contained `Ok` value, leaving an `Err` value untouched. /// - /// If `self` is `Ok` then the value is extracted and passed to `op` - /// whereupon `op`s result is wrapped in `Ok` and returned. if `self` is - /// `Err` then it is immediately returned. This function can be used to - /// compose the results of two functions. + /// This function can be used to compose the results of two functions. /// /// Example: /// - /// let res = do read_file(file).map_move |buf| { + /// let res = do read_file(file).map |buf| { /// parse_bytes(buf) /// } #[inline] - pub fn map_move<U>(self, op: &fn(T) -> U) -> Result<U,E> { + pub fn map<U>(self, op: &fn(T) -> U) -> Result<U,E> { match self { Ok(t) => Ok(op(t)), Err(e) => Err(e) } } - /// Call a method based on a previous result + /// Maps an `Result<T, E>` to `Result<T, F>` by applying a function to an + /// contained `Err` value, leaving an `Ok` value untouched. /// - /// If `self` is `Err` then the value is extracted and passed to `op` - /// whereupon `op`s result is wrapped in an `Err` and returned. if `self` is - /// `Ok` then it is immediately returned. This function can be used to pass - /// through a successful result while handling an error. + /// This function can be used to pass through a successful result while handling + /// an error. #[inline] - pub fn map_err_move<F>(self, op: &fn(E) -> F) -> Result<T,F> { + pub fn map_err<F>(self, op: &fn(E) -> F) -> Result<T,F> { match self { Ok(t) => Ok(t), Err(e) => Err(op(e)) } } - /// Call a method based on a previous result + ///////////////////////////////////////////////////////////////////////// + // Iterator constructors + ///////////////////////////////////////////////////////////////////////// + + /// Returns an `Iterator` over one or zero references to the value of an `Ok` /// - /// If `self` is `Ok`, then `res` it is returned. If `self` is `Err`, - /// then `self` is returned. + /// Example: + /// + /// for buf in read_file(file) { + /// print_buf(buf) + /// } #[inline] - pub fn and(self, res: Result<T, E>) -> Result<T, E> { + pub fn iter<'r>(&'r self) -> OptionIterator<&'r T> { + match *self { + Ok(ref t) => Some(t), + Err(*) => None, + }.move_iter() + } + + /// Returns an `Iterator` over one or zero references to the value of an `Err` + #[inline] + pub fn iter_err<'r>(&'r self) -> OptionIterator<&'r E> { + match *self { + Ok(*) => None, + Err(ref t) => Some(t), + }.move_iter() + } + + //////////////////////////////////////////////////////////////////////// + // Boolean operations on the values, eager and lazy + ///////////////////////////////////////////////////////////////////////// + + /// Returns `res` if the result is `Ok`, otherwise returns the `Err` value of `self`. + #[inline] + pub fn and<U>(self, res: Result<U, E>) -> Result<U, E> { match self { Ok(_) => res, - Err(_) => self, + Err(e) => Err(e), } } - /// Call a method based on a previous result - /// - /// If `self` is `Ok` then the value is extracted and passed to `op` - /// whereupon `op`s result is returned. If `self` is `Err` then it is - /// immediately returned. This function can be used to compose the results - /// of two functions. + /// Calls `op` if the result is `Ok`, otherwise returns the `Err` value of `self`. /// - /// Example: - /// - /// let res = do read_file(file) |buf| { - /// Ok(parse_bytes(buf)) - /// }; + /// This function can be used for control flow based on result values #[inline] pub fn and_then<U>(self, op: &fn(T) -> Result<U, E>) -> Result<U, E> { match self { @@ -206,10 +215,7 @@ impl<T, E: ToStr> Result<T, E> { } } - /// Call a method based on a previous result - /// - /// If `self` is `Ok`, then `self` is returned. If `self` is `Err` - /// then `res` is returned. + /// Returns `res` if the result is `Err`, otherwise returns the `Ok` value of `self`. #[inline] pub fn or(self, res: Result<T, E>) -> Result<T, E> { match self { @@ -218,12 +224,9 @@ impl<T, E: ToStr> Result<T, E> { } } - /// Call a function based on a previous result + /// Calls `op` if the result is `Err`, otherwise returns the `Ok` value of `self`. /// - /// If `self` is `Err` then the value is extracted and passed to `op` - /// whereupon `op`s result is returned. if `self` is `Ok` then it is - /// immediately returned. This function can be used to pass through a - /// successful result while handling an error. + /// This function can be used for control flow based on result values #[inline] pub fn or_else<F>(self, op: &fn(E) -> Result<T, F>) -> Result<T, F> { match self { @@ -231,46 +234,30 @@ impl<T, E: ToStr> Result<T, E> { Err(e) => op(e), } } -} -impl<T: Clone, E: ToStr> Result<T, E> { - /// Call a method based on a previous result - /// - /// If `self` is `Err` then the value is extracted and passed to `op` - /// whereupon `op`s result is wrapped in an `Err` and returned. if `self` is - /// `Ok` then it is immediately returned. This function can be used to pass - /// through a successful result while handling an error. - #[inline] - pub fn map_err<F: Clone>(&self, op: &fn(&E) -> F) -> Result<T,F> { - match *self { - Ok(ref t) => Ok(t.clone()), - Err(ref e) => Err(op(e)) - } - } -} + ///////////////////////////////////////////////////////////////////////// + // Common special cases + ///////////////////////////////////////////////////////////////////////// -impl<T, E: Clone + ToStr> Result<T, E> { - /// Call a method based on a previous result - /// - /// If `self` is `Ok` then the value is extracted and passed to `op` - /// whereupon `op`s result is wrapped in `Ok` and returned. if `self` is - /// `Err` then it is immediately returned. This function can be used to - /// compose the results of two functions. + /// Get a reference to the value out of a successful result /// - /// Example: + /// # Failure /// - /// let res = do read_file(file).map |buf| { - /// parse_bytes(buf) - /// }; + /// If the result is an error #[inline] - pub fn map<U>(&self, op: &fn(&T) -> U) -> Result<U,E> { + pub fn get_ref<'a>(&'a self) -> &'a T { match *self { - Ok(ref t) => Ok(op(t)), - Err(ref e) => Err(e.clone()) + Ok(ref t) => t, + Err(ref e) => fail!("called `Result::get_ref()` on `Err` value '{}'", + e.to_str()), } } } +///////////////////////////////////////////////////////////////////////////// +// Constructor extension trait +///////////////////////////////////////////////////////////////////////////// + /// A generic trait for converting a value to a `Result` pub trait ToResult<T, E> { /// Convert to the `result` type @@ -289,6 +276,30 @@ pub trait AsResult<T, E> { fn as_result<'a>(&'a self) -> Result<&'a T, &'a E>; } +impl<T: Clone, E: Clone> ToResult<T, E> for Result<T, E> { + #[inline] + fn to_result(&self) -> Result<T, E> { self.clone() } +} + +impl<T, E> IntoResult<T, E> for Result<T, E> { + #[inline] + fn into_result(self) -> Result<T, E> { self } +} + +impl<T, E> AsResult<T, E> for Result<T, E> { + #[inline] + fn as_result<'a>(&'a self) -> Result<&'a T, &'a E> { + match *self { + Ok(ref t) => Ok(t), + Err(ref e) => Err(e), + } + } +} + +///////////////////////////////////////////////////////////////////////////// +// Trait implementations +///////////////////////////////////////////////////////////////////////////// + impl<T: Clone, E> option::ToOption<T> for Result<T, E> { #[inline] fn to_option(&self) -> Option<T> { @@ -319,26 +330,6 @@ impl<T, E> option::AsOption<T> for Result<T, E> { } } -impl<T: Clone, E: Clone> ToResult<T, E> for Result<T, E> { - #[inline] - fn to_result(&self) -> Result<T, E> { self.clone() } -} - -impl<T, E> IntoResult<T, E> for Result<T, E> { - #[inline] - fn into_result(self) -> Result<T, E> { self } -} - -impl<T, E> AsResult<T, E> for Result<T, E> { - #[inline] - fn as_result<'a>(&'a self) -> Result<&'a T, &'a E> { - match *self { - Ok(ref t) => Ok(t), - Err(ref e) => Err(e), - } - } -} - impl<T: Clone, E: Clone> either::ToEither<E, T> for Result<T, E> { #[inline] fn to_either(&self) -> either::Either<E, T> { @@ -389,6 +380,10 @@ impl<T: fmt::Default, E: fmt::Default> fmt::Default for Result<T, E> { } } +///////////////////////////////////////////////////////////////////////////// +// Free functions +///////////////////////////////////////////////////////////////////////////// + /// Takes each element in the iterator: if it is an error, no further /// elements are taken, and the error is returned. /// Should no error occur, a vector containing the values of each Result @@ -450,6 +445,9 @@ pub fn fold_<T, E, Iter: Iterator<Result<T, E>>>( fold(iterator, (), |_, _| ()) } +///////////////////////////////////////////////////////////////////////////// +// Tests +///////////////////////////////////////////////////////////////////////////// #[cfg(test)] mod tests { @@ -460,7 +458,6 @@ mod tests { use iter::range; use option::{IntoOption, ToOption, AsOption}; use option; - use str::OwnedStr; use vec::ImmutableVector; use to_str::ToStr; @@ -470,10 +467,10 @@ mod tests { #[test] pub fn test_and() { assert_eq!(op1().and(Ok(667)).unwrap(), 667); - assert_eq!(op1().and(Err(~"bad")).unwrap_err(), ~"bad"); + assert_eq!(op1().and(Err::<(), ~str>(~"bad")).unwrap_err(), ~"bad"); assert_eq!(op2().and(Ok(667)).unwrap_err(), ~"sadface"); - assert_eq!(op2().and(Err(~"bad")).unwrap_err(), ~"sadface"); + assert_eq!(op2().and(Err::<(), ~str>(~"bad")).unwrap_err(), ~"sadface"); } #[test] @@ -530,26 +527,14 @@ mod tests { #[test] pub fn test_impl_map() { - assert_eq!(Ok::<~str, ~str>(~"a").map(|x| (~"b").append(*x)), Ok(~"ba")); - assert_eq!(Err::<~str, ~str>(~"a").map(|x| (~"b").append(*x)), Err(~"a")); + assert_eq!(Ok::<~str, ~str>(~"a").map(|x| x + "b"), Ok(~"ab")); + assert_eq!(Err::<~str, ~str>(~"a").map(|x| x + "b"), Err(~"a")); } #[test] pub fn test_impl_map_err() { - assert_eq!(Ok::<~str, ~str>(~"a").map_err(|x| (~"b").append(*x)), Ok(~"a")); - assert_eq!(Err::<~str, ~str>(~"a").map_err(|x| (~"b").append(*x)), Err(~"ba")); - } - - #[test] - pub fn test_impl_map_move() { - assert_eq!(Ok::<~str, ~str>(~"a").map_move(|x| x + "b"), Ok(~"ab")); - assert_eq!(Err::<~str, ~str>(~"a").map_move(|x| x + "b"), Err(~"a")); - } - - #[test] - pub fn test_impl_map_err_move() { - assert_eq!(Ok::<~str, ~str>(~"a").map_err_move(|x| x + "b"), Ok(~"a")); - assert_eq!(Err::<~str, ~str>(~"a").map_err_move(|x| x + "b"), Err(~"ab")); + assert_eq!(Ok::<~str, ~str>(~"a").map_err(|x| x + "b"), Ok(~"a")); + assert_eq!(Err::<~str, ~str>(~"a").map_err(|x| x + "b"), Err(~"ab")); } #[test] |
