auto merge of #10119 : Kimundi/rust/option_and_generic, r=alexcrichton

This takes the last reforms on the `Option` type and applies them to `Result` too. For that, I reordered and grouped the functions in both modules, and also did some refactorings:

- Added `as_ref` and `as_mut` adapters to `Result`.
- Renamed `Result::map_move` to `Result::map` (same for `_err` variant), deleted other map functions. 
- Made the `.expect()` methods be generic over anything you can
  fail with.
- Updated some doc comments to the line doc comment style
- Cleaned up and extended standard trait implementations on `Option` and `Result`
- Removed legacy implementations in the `option` and `result` module
This commit is contained in:
bors 2013-11-01 09:36:25 -07:00
commit 7cff3c74b8
8 changed files with 470 additions and 577 deletions

View File

@ -4560,14 +4560,14 @@ pub fn count_traits_and_supertraits(tcx: ctxt,
}
pub fn get_tydesc_ty(tcx: ctxt) -> Result<t, ~str> {
do tcx.lang_items.require(TyDescStructLangItem).map_move |tydesc_lang_item| {
do tcx.lang_items.require(TyDescStructLangItem).map |tydesc_lang_item| {
tcx.intrinsic_defs.find_copy(&tydesc_lang_item)
.expect("Failed to resolve TyDesc")
}
}
pub fn get_opaque_ty(tcx: ctxt) -> Result<t, ~str> {
do tcx.lang_items.require(OpaqueStructLangItem).map_move |opaque_lang_item| {
do tcx.lang_items.require(OpaqueStructLangItem).map |opaque_lang_item| {
tcx.intrinsic_defs.find_copy(&opaque_lang_item)
.expect("Failed to resolve Opaque")
}

View File

@ -2464,7 +2464,7 @@ fn test_timer_sleep_simple() {
unsafe {
let io = local_io();
let timer = io.timer_init();
do timer.map_move |mut t| { t.sleep(1) };
do timer.map |mut t| { t.sleep(1) };
}
}
}

View File

@ -8,94 +8,86 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/*!
Operations on the ubiquitous `Option` type.
Type `Option` represents an optional value.
Every `Option<T>` value can either be `Some(T)` or `None`. Where in other
languages you might use a nullable type, in Rust you would use an option
type.
Options are most commonly used with pattern matching to query the presence
of a value and take action, always accounting for the `None` case.
# Example
```
let msg = Some(~"howdy");
// Take a reference to the contained string
match msg {
Some(ref m) => io::println(*m),
None => ()
}
// Remove the contained string, destroying the Option
let unwrapped_msg = match msg {
Some(m) => m,
None => ~"default message"
};
```
*/
//! Operations on the ubiquitous `Option` type.
//!
//! Type `Option` represents an optional value.
//!
//! Every `Option<T>` value can either be `Some(T)` or `None`. Where in other
//! languages you might use a nullable type, in Rust you would use an option
//! type.
//!
//! Options are most commonly used with pattern matching to query the presence
//! of a value and take action, always accounting for the `None` case.
//!
//! # Example
//!
//! ```
//! let msg = Some(~"howdy");
//!
//! // Take a reference to the contained string
//! match msg {
//! Some(ref m) => io::println(*m),
//! None => ()
//! }
//!
//! // Remove the contained string, destroying the Option
//! let unwrapped_msg = match msg {
//! Some(m) => m,
//! None => ~"default message"
//! };
//! ```
use any::Any;
use clone::Clone;
use cmp::{Eq,Ord};
use default::Default;
use either;
use util;
use num::Zero;
use iter;
use iter::{Iterator, DoubleEndedIterator, ExactSize};
use result;
use str::{StrSlice, OwnedStr};
use to_str::ToStr;
use clone::DeepClone;
use cmp::{Eq, TotalEq, TotalOrd};
use default::Default;
use fmt;
use iter::{Iterator, DoubleEndedIterator, ExactSize};
use kinds::Send;
use result::{IntoResult, ToResult, AsResult};
use result::{Result, Ok, Err};
use str::OwnedStr;
use to_str::ToStr;
use util;
/// The option type
#[deriving(Clone, DeepClone, Eq)]
#[allow(missing_doc)]
#[deriving(Clone, DeepClone, Eq, Ord, TotalEq, TotalOrd, ToStr)]
pub enum Option<T> {
/// No value
None,
Some(T),
/// Some value `T`
Some(T)
}
impl<T: Eq + Ord> Ord for Option<T> {
fn lt(&self, other: &Option<T>) -> bool {
iter::order::lt(self.iter(), other.iter())
}
fn le(&self, other: &Option<T>) -> bool {
iter::order::le(self.iter(), other.iter())
}
fn ge(&self, other: &Option<T>) -> bool {
iter::order::ge(self.iter(), other.iter())
}
fn gt(&self, other: &Option<T>) -> bool {
iter::order::gt(self.iter(), other.iter())
}
}
// FIXME: #8242 implementing manually because deriving doesn't work for some reason
impl<T: ToStr> ToStr for Option<T> {
fn to_str(&self) -> ~str {
match *self {
Some(ref x) => {
let mut s = ~"Some(";
s.push_str(x.to_str());
s.push_str(")");
s
}
None => ~"None"
}
}
}
/////////////////////////////////////////////////////////////////////////////
// Type implementation
/////////////////////////////////////////////////////////////////////////////
impl<T> Option<T> {
/////////////////////////////////////////////////////////////////////////
// Querying the contained values
/////////////////////////////////////////////////////////////////////////
/// Returns true if the option contains a `Some` value
#[inline]
pub fn is_some(&self) -> bool {
match *self {
Some(_) => true,
None => false
}
}
/// Returns true if the option equals `None`
#[inline]
pub fn is_none(&self) -> bool {
!self.is_some()
}
/////////////////////////////////////////////////////////////////////////
// Adapter for working with references
/////////////////////////////////////////////////////////////////////////
/// Convert from `Option<T>` to `Option<&T>`
#[inline]
pub fn as_ref<'r>(&'r self) -> Option<&'r T> {
@ -108,6 +100,64 @@ impl<T> Option<T> {
match *self { Some(ref mut x) => Some(x), None => None }
}
/////////////////////////////////////////////////////////////////////////
// Getting to contained values
/////////////////////////////////////////////////////////////////////////
/// Unwraps a option, yielding the content of a `Some`
/// Fails if the value is a `None` with a custom failure message provided by `msg`.
#[inline]
pub fn expect<M: Any + Send>(self, msg: M) -> T {
match self {
Some(val) => val,
None => fail!(msg),
}
}
/// Moves a value out of an option type and returns it.
///
/// Useful primarily for getting strings, vectors and unique pointers out
/// of option types without copying them.
///
/// # Failure
///
/// Fails if the value equals `None`.
///
/// # Safety note
///
/// In general, because this function may fail, its use is discouraged.
/// Instead, prefer to use pattern matching and handle the `None`
/// case explicitly.
#[inline]
pub fn unwrap(self) -> T {
match self {
Some(val) => val,
None => fail!("called `Option::unwrap()` on a `None` value"),
}
}
/// Returns the contained value or a default
#[inline]
pub fn unwrap_or(self, def: T) -> T {
match self {
Some(x) => x,
None => def
}
}
/// Returns the contained value or computes it from a closure
#[inline]
pub fn unwrap_or_else(self, f: &fn() -> T) -> T {
match self {
Some(x) => x,
None => f()
}
}
/////////////////////////////////////////////////////////////////////////
// Transforming contained values
/////////////////////////////////////////////////////////////////////////
/// Maps an `Option<T>` to `Option<U>` by applying a function to a contained value.
#[inline]
pub fn map<U>(self, f: &fn(T) -> U) -> Option<U> {
@ -120,6 +170,31 @@ impl<T> Option<T> {
match self { None => def, Some(t) => f(t) }
}
/// Apply a function to the contained value or do nothing.
/// Returns true if the contained value was mutated.
pub fn mutate(&mut self, f: &fn(T) -> T) -> bool {
if self.is_some() {
*self = Some(f(self.take_unwrap()));
true
} else { false }
}
/// Apply a function to the contained value or set it to a default.
/// Returns true if the contained value was mutated, or false if set to the default.
pub fn mutate_default(&mut self, def: T, f: &fn(T) -> T) -> bool {
if self.is_some() {
*self = Some(f(self.take_unwrap()));
true
} else {
*self = Some(def);
false
}
}
/////////////////////////////////////////////////////////////////////////
// Iterator constructors
/////////////////////////////////////////////////////////////////////////
/// Return an iterator over the possibly contained value
#[inline]
pub fn iter<'r>(&'r self) -> OptionIterator<&'r T> {
@ -144,19 +219,13 @@ impl<T> Option<T> {
OptionIterator{opt: self}
}
/// Returns true if the option equals `None`
#[inline]
pub fn is_none(&self) -> bool {
match *self { None => true, Some(_) => false }
}
/// Returns true if the option contains a `Some` value
#[inline]
pub fn is_some(&self) -> bool { !self.is_none() }
/////////////////////////////////////////////////////////////////////////
// Boolean operations on the values, eager and lazy
/////////////////////////////////////////////////////////////////////////
/// Returns `None` if the option is `None`, otherwise returns `optb`.
#[inline]
pub fn and(self, optb: Option<T>) -> Option<T> {
pub fn and<U>(self, optb: Option<U>) -> Option<U> {
match self {
Some(_) => optb,
None => None,
@ -192,7 +261,17 @@ impl<T> Option<T> {
}
}
/// Filters an optional value using given function.
/////////////////////////////////////////////////////////////////////////
// Misc
/////////////////////////////////////////////////////////////////////////
/// Take the value out of the option, leaving a `None` in its place.
#[inline]
pub fn take(&mut self) -> Option<T> {
util::replace(self, None)
}
/// Filters an optional value using a given function.
#[inline(always)]
pub fn filtered(self, f: &fn(t: &T) -> bool) -> Option<T> {
match self {
@ -201,33 +280,33 @@ impl<T> Option<T> {
}
}
/// Take the value out of the option, leaving a `None` in its place.
/// Applies a function zero or more times until the result is `None`.
#[inline]
pub fn take(&mut self) -> Option<T> {
util::replace(self, None)
}
/// Apply a function to the contained value or do nothing.
/// Returns true if the contained value was mutated.
pub fn mutate(&mut self, f: &fn(T) -> T) -> bool {
if self.is_some() {
*self = Some(f(self.take_unwrap()));
true
} else { false }
}
/// Apply a function to the contained value or set it to a default.
/// Returns true if the contained value was mutated, or false if set to the default.
pub fn mutate_default(&mut self, def: T, f: &fn(T) -> T) -> bool {
if self.is_some() {
*self = Some(f(self.take_unwrap()));
true
} else {
*self = Some(def);
false
pub fn while_some(self, blk: &fn(v: T) -> Option<T>) {
let mut opt = self;
while opt.is_some() {
opt = blk(opt.unwrap());
}
}
/////////////////////////////////////////////////////////////////////////
// Common special cases
/////////////////////////////////////////////////////////////////////////
/// The option dance. Moves a value out of an option type and returns it,
/// replacing the original with `None`.
///
/// # Failure
///
/// Fails if the value equals `None`.
#[inline]
pub fn take_unwrap(&mut self) -> T {
if self.is_none() {
fail!("called `Option::take_unwrap()` on a `None` value")
}
self.take().unwrap()
}
/// Gets an immutable reference to the value inside an option.
///
/// # Failure
@ -267,85 +346,23 @@ impl<T> Option<T> {
None => fail!("called `Option::get_mut_ref()` on a `None` value"),
}
}
}
/// Moves a value out of an option type and returns it.
///
/// Useful primarily for getting strings, vectors and unique pointers out
/// of option types without copying them.
///
/// # Failure
///
/// Fails if the value equals `None`.
///
/// # Safety note
///
/// In general, because this function may fail, its use is discouraged.
/// Instead, prefer to use pattern matching and handle the `None`
/// case explicitly.
impl<T: Default> Option<T> {
/// Returns the contained value or default (for this type)
#[inline]
pub fn unwrap(self) -> T {
pub fn unwrap_or_default(self) -> T {
match self {
Some(x) => x,
None => fail!("called `Option::unwrap()` on a `None` value"),
}
}
/// The option dance. Moves a value out of an option type and returns it,
/// replacing the original with `None`.
///
/// # Failure
///
/// Fails if the value equals `None`.
#[inline]
pub fn take_unwrap(&mut self) -> T {
if self.is_none() {
fail!("called `Option::take_unwrap()` on a `None` value")
}
self.take().unwrap()
}
/// Gets the value out of an option, printing a specified message on
/// failure
///
/// # Failure
///
/// Fails if the value equals `None`
#[inline]
pub fn expect(self, reason: &str) -> T {
match self {
Some(val) => val,
None => fail!("{}", reason.to_owned()),
}
}
/// Returns the contained value or a default
#[inline]
pub fn unwrap_or(self, def: T) -> T {
match self {
Some(x) => x,
None => def
}
}
/// Returns the contained value or computes it from a closure
#[inline]
pub fn unwrap_or_else(self, f: &fn() -> T) -> T {
match self {
Some(x) => x,
None => f()
}
}
/// Applies a function zero or more times until the result is `None`.
#[inline]
pub fn while_some(self, blk: &fn(v: T) -> Option<T>) {
let mut opt = self;
while opt.is_some() {
opt = blk(opt.unwrap());
None => Default::default()
}
}
}
/////////////////////////////////////////////////////////////////////////////
// Constructor extension trait
/////////////////////////////////////////////////////////////////////////////
/// A generic trait for converting a value to a `Option`
pub trait ToOption<T> {
/// Convert to the `option` type
@ -384,53 +401,47 @@ impl<T> AsOption<T> for Option<T> {
}
}
impl<T: Clone> result::ToResult<T, ()> for Option<T> {
/////////////////////////////////////////////////////////////////////////////
// Trait implementations
/////////////////////////////////////////////////////////////////////////////
impl<T: Clone> ToResult<T, ()> for Option<T> {
#[inline]
fn to_result(&self) -> result::Result<T, ()> {
fn to_result(&self) -> Result<T, ()> {
match *self {
Some(ref x) => result::Ok(x.clone()),
None => result::Err(()),
Some(ref x) => Ok(x.clone()),
None => Err(()),
}
}
}
impl<T> result::IntoResult<T, ()> for Option<T> {
impl<T> IntoResult<T, ()> for Option<T> {
#[inline]
fn into_result(self) -> result::Result<T, ()> {
fn into_result(self) -> Result<T, ()> {
match self {
Some(x) => result::Ok(x),
None => result::Err(()),
Some(x) => Ok(x),
None => Err(()),
}
}
}
impl<T: Clone> either::ToEither<(), T> for Option<T> {
impl<T> AsResult<T, ()> for Option<T> {
#[inline]
fn to_either(&self) -> either::Either<(), T> {
fn as_result<'a>(&'a self) -> Result<&'a T, &'a ()> {
static UNIT: () = ();
match *self {
Some(ref x) => either::Right(x.clone()),
None => either::Left(()),
Some(ref t) => Ok(t),
None => Err(&UNIT),
}
}
}
impl<T> either::IntoEither<(), T> for Option<T> {
impl<T: fmt::Default> fmt::Default for Option<T> {
#[inline]
fn into_either(self) -> either::Either<(), T> {
match self {
Some(x) => either::Right(x),
None => either::Left(()),
}
}
}
impl<T: Default> Option<T> {
/// Returns the contained value or default (for this type)
#[inline]
pub fn unwrap_or_default(self) -> T {
match self {
Some(x) => x,
None => Default::default()
fn fmt(s: &Option<T>, f: &mut fmt::Formatter) {
match *s {
Some(ref t) => write!(f.buf, "Some({})", *t),
None => write!(f.buf, "None")
}
}
}
@ -440,16 +451,9 @@ impl<T> Default for Option<T> {
fn default() -> Option<T> { None }
}
impl<T: Zero> Option<T> {
/// Returns the contained value or zero (for this type)
#[inline]
pub fn unwrap_or_zero(self) -> T {
match self {
Some(x) => x,
None => Zero::zero()
}
}
}
/////////////////////////////////////////////////////////////////////////////
// The Option Iterator
/////////////////////////////////////////////////////////////////////////////
/// An iterator that yields either one or zero elements
#[deriving(Clone, DeepClone)]
@ -481,14 +485,17 @@ impl<A> DoubleEndedIterator<A> for OptionIterator<A> {
impl<A> ExactSize<A> for OptionIterator<A> {}
/////////////////////////////////////////////////////////////////////////////
// Tests
/////////////////////////////////////////////////////////////////////////////
#[cfg(test)]
mod tests {
use super::*;
use either::{IntoEither, ToEither};
use either;
use result::{IntoResult, ToResult};
use result;
use result::{Ok, Err};
use str::StrSlice;
use util;
#[test]
@ -550,6 +557,7 @@ mod tests {
assert_eq!(y2, 5);
assert!(y.is_none());
}
#[test] #[should_fail]
fn test_option_too_much_dance() {
let mut y = Some(util::NonCopyable);
@ -561,11 +569,11 @@ mod tests {
fn test_and() {
let x: Option<int> = Some(1);
assert_eq!(x.and(Some(2)), Some(2));
assert_eq!(x.and(None), None);
assert_eq!(x.and(None::<int>), None);
let x: Option<int> = None;
assert_eq!(x.and(Some(2)), None);
assert_eq!(x.and(None), None);
assert_eq!(x.and(None::<int>), None);
}
#[test]
@ -630,7 +638,7 @@ mod tests {
#[test]
#[should_fail]
fn test_unwrap_fail() {
fn test_unwrap_fail2() {
let x: Option<~str> = None;
x.unwrap();
}
@ -653,14 +661,6 @@ mod tests {
assert_eq!(x.unwrap_or_else(|| 2), 2);
}
#[test]
fn test_unwrap_or_zero() {
let some_stuff = Some(42);
assert_eq!(some_stuff.unwrap_or_zero(), 42);
let no_stuff: Option<int> = None;
assert_eq!(no_stuff.unwrap_or_zero(), 0);
}
#[test]
fn test_filtered() {
let some_stuff = Some(42);
@ -765,8 +765,8 @@ mod tests {
let some: Option<int> = Some(100);
let none: Option<int> = None;
assert_eq!(some.to_result(), result::Ok(100));
assert_eq!(none.to_result(), result::Err(()));
assert_eq!(some.to_result(), Ok(100));
assert_eq!(none.to_result(), Err(()));
}
#[test]
@ -774,25 +774,7 @@ mod tests {
let some: Option<int> = Some(100);
let none: Option<int> = None;
assert_eq!(some.into_result(), result::Ok(100));
assert_eq!(none.into_result(), result::Err(()));
}
#[test]
pub fn test_to_either() {
let some: Option<int> = Some(100);
let none: Option<int> = None;
assert_eq!(some.to_either(), either::Right(100));
assert_eq!(none.to_either(), either::Left(()));
}
#[test]
pub fn test_into_either() {
let some: Option<int> = Some(100);
let none: Option<int> = None;
assert_eq!(some.into_either(), either::Right(100));
assert_eq!(none.into_either(), either::Left(()));
assert_eq!(some.into_result(), Ok(100));
assert_eq!(none.into_result(), Err(()));
}
}

View File

@ -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,26 +10,25 @@
//! A type representing either success or failure
#[allow(missing_doc)];
use any::Any;
use clone::Clone;
use cmp::Eq;
use either;
use iter::Iterator;
use option::{None, Option, Some, OptionIterator};
use option;
use vec;
use vec::OwnedVector;
use to_str::ToStr;
use str::StrSlice;
use fmt;
use iter::Iterator;
use kinds::Send;
use option::{None, Option, Some, OptionIterator};
use option::{ToOption, IntoOption, AsOption};
use str::OwnedStr;
use to_str::ToStr;
use vec::OwnedVector;
use vec;
/// `Result` is a type that represents either success (`Ok`) or failure (`Err`).
///
/// In order to provide informative error messages, `E` is required to implement `ToStr`.
/// It is further recommended for `E` to be a descriptive error type, eg a `enum` for
/// all possible errors cases.
#[deriving(Clone, Eq)]
#[deriving(Clone, DeepClone, Eq, Ord, TotalEq, TotalOrd, ToStr)]
pub enum Result<T, E> {
/// Contains the successful result value
Ok(T),
@ -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,12 +60,114 @@ impl<T, E: ToStr> Result<T, E> {
!self.is_ok()
}
/// Call a method based on a previous result
/////////////////////////////////////////////////////////////////////////
// Adapter for working with references
/////////////////////////////////////////////////////////////////////////
/// Convert from `Result<T, E>` to `Result<&T, &E>`
#[inline]
pub fn as_ref<'r>(&'r self) -> Result<&'r T, &'r E> {
match *self {
Ok(ref x) => Ok(x),
Err(ref x) => Err(x),
}
}
/// Convert from `Result<T, E>` to `Result<&mut T, &mut E>`
#[inline]
pub fn as_mut<'r>(&'r mut self) -> Result<&'r mut T, &'r mut E> {
match *self {
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 a custom failure message provided by `msg`.
#[inline]
pub fn expect<M: Any + Send>(self, msg: M) -> T {
match self {
Ok(t) => t,
Err(_) => fail!(msg),
}
}
/// Unwraps a result, yielding the content of an `Err`.
/// Fails if the value is a `Ok` with a custom failure message provided by `msg`.
#[inline]
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 an error message derived
/// from `E`'s `ToStr` implementation.
#[inline]
pub fn unwrap(self) -> T {
match self {
Ok(t) => t,
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`.
#[inline]
pub fn unwrap_err(self) -> E {
match self {
Ok(_) => fail!("called `Result::unwrap_err()` on an `Ok` value"),
Err(e) => e
}
}
/////////////////////////////////////////////////////////////////////////
// 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 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 |buf| {
/// parse_bytes(buf)
/// }
#[inline]
pub fn map<U>(self, op: &fn(T) -> U) -> Result<U,E> {
match self {
Ok(t) => Ok(op(t)),
Err(e) => Err(e)
}
}
/// Maps an `Result<T, E>` to `Result<T, F>` by applying a function to an
/// contained `Err` value, leaving an `Ok` value untouched.
///
/// This function can be used to pass through a successful result while handling
/// an error.
#[inline]
pub fn map_err<F>(self, op: &fn(E) -> F) -> Result<T,F> {
match self {
Ok(t) => Ok(t),
Err(e) => Err(op(e))
}
}
/////////////////////////////////////////////////////////////////////////
// Iterator constructors
/////////////////////////////////////////////////////////////////////////
/// Returns an `Iterator` over one or zero references to the value of an `Ok`
///
/// Example:
///
@ -87,12 +182,7 @@ impl<T, E: ToStr> Result<T, E> {
}.move_iter()
}
/// 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.
/// 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 {
@ -101,103 +191,22 @@ impl<T, E: ToStr> Result<T, E> {
}.move_iter()
}
/// 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.
#[inline]
pub fn unwrap(self) -> T {
match self {
Ok(t) => t,
Err(e) => fail!("called `Result::unwrap()` on `Err` value: {}",
e.to_str()),
}
}
////////////////////////////////////////////////////////////////////////
// Boolean operations on the values, eager and lazy
/////////////////////////////////////////////////////////////////////////
/// Unwraps a result, yielding the content of an `Err`.
/// Fails if the value is a `Ok`.
/// Returns `res` if the result is `Ok`, otherwise returns the `Err` value of `self`.
#[inline]
pub fn unwrap_err(self) -> E {
self.expect_err("called `Result::unwrap_err()` on `Ok` value")
}
/// Unwraps a result, yielding the content of an `Ok`.
/// Fails if the value is a `Err` with a custom failure message.
#[inline]
pub fn expect(self, reason: &str) -> T {
match self {
Ok(t) => t,
Err(_) => fail!("{}", reason.to_owned()),
}
}
/// Unwraps a result, yielding the content of an `Err`
/// Fails if the value is a `Ok` with a custom failure message.
#[inline]
pub fn expect_err(self, reason: &str) -> E {
match self {
Err(e) => e,
Ok(_) => fail!("{}", reason.to_owned()),
}
}
/// 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.
///
/// Example:
///
/// let res = do read_file(file).map_move |buf| {
/// parse_bytes(buf)
/// }
#[inline]
pub fn map_move<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
///
/// 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_move<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
///
/// If `self` is `Ok`, then `res` it is returned. If `self` is `Err`,
/// then `self` is returned.
#[inline]
pub fn and(self, res: Result<T, E>) -> Result<T, E> {
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
/// Calls `op` if the result is `Ok`, otherwise returns the `Err` value of `self`.
///
/// 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:
///
/// 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,45 +234,29 @@ 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
/////////////////////////////////////////////////////////////////////////
// Common special cases
/////////////////////////////////////////////////////////////////////////
/// Get a reference to the value out of a successful 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.
/// # Failure
///
/// If the result is an error
#[inline]
pub fn map_err<F: Clone>(&self, op: &fn(&E) -> F) -> Result<T,F> {
pub fn get_ref<'a>(&'a self) -> &'a T {
match *self {
Ok(ref t) => Ok(t.clone()),
Err(ref e) => Err(op(e))
Ok(ref t) => t,
Err(ref e) => fail!("called `Result::get_ref()` on `Err` value '{}'",
e.to_str()),
}
}
}
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.
///
/// Example:
///
/// let res = do read_file(file).map |buf| {
/// parse_bytes(buf)
/// };
#[inline]
pub fn map<U>(&self, op: &fn(&T) -> U) -> Result<U,E> {
match *self {
Ok(ref t) => Ok(op(t)),
Err(ref e) => Err(e.clone())
}
}
}
/////////////////////////////////////////////////////////////////////////////
// Constructor extension trait
/////////////////////////////////////////////////////////////////////////////
/// A generic trait for converting a value to a `Result`
pub trait ToResult<T, E> {
@ -289,36 +276,6 @@ pub trait AsResult<T, E> {
fn as_result<'a>(&'a self) -> Result<&'a T, &'a E>;
}
impl<T: Clone, E> option::ToOption<T> for Result<T, E> {
#[inline]
fn to_option(&self) -> Option<T> {
match *self {
Ok(ref t) => Some(t.clone()),
Err(_) => None,
}
}
}
impl<T, E> option::IntoOption<T> for Result<T, E> {
#[inline]
fn into_option(self) -> Option<T> {
match self {
Ok(t) => Some(t),
Err(_) => None,
}
}
}
impl<T, E> option::AsOption<T> for Result<T, E> {
#[inline]
fn as_option<'a>(&'a self) -> Option<&'a T> {
match *self {
Ok(ref t) => Some(t),
Err(_) => None,
}
}
}
impl<T: Clone, E: Clone> ToResult<T, E> for Result<T, E> {
#[inline]
fn to_result(&self) -> Result<T, E> { self.clone() }
@ -339,42 +296,36 @@ impl<T, E> AsResult<T, E> for Result<T, E> {
}
}
impl<T: Clone, E: Clone> either::ToEither<E, T> for Result<T, E> {
/////////////////////////////////////////////////////////////////////////////
// Trait implementations
/////////////////////////////////////////////////////////////////////////////
impl<T: Clone, E> ToOption<T> for Result<T, E> {
#[inline]
fn to_either(&self) -> either::Either<E, T> {
fn to_option(&self) -> Option<T> {
match *self {
Ok(ref t) => either::Right(t.clone()),
Err(ref e) => either::Left(e.clone()),
Ok(ref t) => Some(t.clone()),
Err(_) => None,
}
}
}
impl<T, E> either::IntoEither<E, T> for Result<T, E> {
impl<T, E> IntoOption<T> for Result<T, E> {
#[inline]
fn into_either(self) -> either::Either<E, T> {
fn into_option(self) -> Option<T> {
match self {
Ok(t) => either::Right(t),
Err(e) => either::Left(e),
Ok(t) => Some(t),
Err(_) => None,
}
}
}
impl<T, E> either::AsEither<E, T> for Result<T, E> {
impl<T, E> AsOption<T> for Result<T, E> {
#[inline]
fn as_either<'a>(&'a self) -> either::Either<&'a E, &'a T> {
fn as_option<'a>(&'a self) -> Option<&'a T> {
match *self {
Ok(ref t) => either::Right(t),
Err(ref e) => either::Left(e),
}
}
}
impl<T: ToStr, E: ToStr> ToStr for Result<T, E> {
#[inline]
fn to_str(&self) -> ~str {
match *self {
Ok(ref t) => format!("Ok({:s})", t.to_str()),
Err(ref e) => format!("Err({:s})", e.to_str())
Ok(ref t) => Some(t),
Err(_) => None,
}
}
}
@ -389,6 +340,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,17 +405,17 @@ pub fn fold_<T, E, Iter: Iterator<Result<T, E>>>(
fold(iterator, (), |_, _| ())
}
/////////////////////////////////////////////////////////////////////////////
// Tests
/////////////////////////////////////////////////////////////////////////////
#[cfg(test)]
mod tests {
use super::*;
use either::{IntoEither, ToEither, AsEither};
use either;
use iter::range;
use option::{IntoOption, ToOption, AsOption};
use option;
use str::OwnedStr;
use option::{Some, None};
use vec::ImmutableVector;
use to_str::ToStr;
@ -470,10 +425,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 +485,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]
@ -603,8 +546,8 @@ mod tests {
let ok: Result<int, int> = Ok(100);
let err: Result<int, int> = Err(404);
assert_eq!(ok.to_option(), option::Some(100));
assert_eq!(err.to_option(), option::None);
assert_eq!(ok.to_option(), Some(100));
assert_eq!(err.to_option(), None);
}
#[test]
@ -612,8 +555,8 @@ mod tests {
let ok: Result<int, int> = Ok(100);
let err: Result<int, int> = Err(404);
assert_eq!(ok.into_option(), option::Some(100));
assert_eq!(err.into_option(), option::None);
assert_eq!(ok.into_option(), Some(100));
assert_eq!(err.into_option(), None);
}
#[test]
@ -622,7 +565,7 @@ mod tests {
let err: Result<int, int> = Err(404);
assert_eq!(ok.as_option().unwrap(), &100);
assert_eq!(err.as_option(), option::None);
assert_eq!(err.as_option(), None);
}
#[test]
@ -655,33 +598,6 @@ mod tests {
assert_eq!(err.as_result(), Err(&x));
}
#[test]
pub fn test_to_either() {
let ok: Result<int, int> = Ok(100);
let err: Result<int, int> = Err(404);
assert_eq!(ok.to_either(), either::Right(100));
assert_eq!(err.to_either(), either::Left(404));
}
#[test]
pub fn test_into_either() {
let ok: Result<int, int> = Ok(100);
let err: Result<int, int> = Err(404);
assert_eq!(ok.into_either(), either::Right(100));
assert_eq!(err.into_either(), either::Left(404));
}
#[test]
pub fn test_as_either() {
let ok: Result<int, int> = Ok(100);
let err: Result<int, int> = Err(404);
assert_eq!(ok.as_either().unwrap_right(), &100);
assert_eq!(err.as_either().unwrap_left(), &404);
}
#[test]
pub fn test_to_str() {
let ok: Result<int, ~str> = Ok(100);

View File

@ -208,7 +208,7 @@ impl Reader for StdReader {
fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
let ret = match self.inner {
TTY(ref mut tty) => tty.read(buf),
File(ref mut file) => file.read(buf).map_move(|i| i as uint),
File(ref mut file) => file.read(buf).map(|i| i as uint),
};
match ret {
Ok(amt) => Some(amt as uint),

View File

@ -8,45 +8,40 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/*!
# The Rust standard library
The Rust standard library is a group of interrelated modules defining
the core language traits, operations on built-in data types, collections,
platform abstractions, the task scheduler, runtime support for language
features and other common functionality.
`std` includes modules corresponding to each of the integer types,
each of the floating point types, the `bool` type, tuples, characters,
strings (`str`), vectors (`vec`), managed boxes (`managed`), owned
boxes (`owned`), and unsafe and borrowed pointers (`ptr`, `borrowed`).
Additionally, `std` provides pervasive types (`option` and `result`),
task creation and communication primitives (`task`, `comm`), platform
abstractions (`os` and `path`), basic I/O abstractions (`io`), common
traits (`kinds`, `ops`, `cmp`, `num`, `to_str`), and complete bindings
to the C standard library (`libc`).
# Standard library injection and the Rust prelude
`std` is imported at the topmost level of every crate by default, as
if the first line of each crate was
extern mod std;
This means that the contents of std can be accessed from any context
with the `std::` path prefix, as in `use std::vec`, `use std::task::spawn`,
etc.
Additionally, `std` contains a `prelude` module that reexports many of the
most common types, traits and functions. The contents of the prelude are
imported into every *module* by default. Implicitly, all modules behave as if
they contained the following prologue:
use std::prelude::*;
*/
//! # The Rust standard library
//!
//! The Rust standard library is a group of interrelated modules defining
//! the core language traits, operations on built-in data types, collections,
//! platform abstractions, the task scheduler, runtime support for language
//! features and other common functionality.
//!
//! `std` includes modules corresponding to each of the integer types,
//! each of the floating point types, the `bool` type, tuples, characters,
//! strings (`str`), vectors (`vec`), managed boxes (`managed`), owned
//! boxes (`owned`), and unsafe and borrowed pointers (`ptr`, `borrowed`).
//! Additionally, `std` provides pervasive types (`option` and `result`),
//! task creation and communication primitives (`task`, `comm`), platform
//! abstractions (`os` and `path`), basic I/O abstractions (`io`), common
//! traits (`kinds`, `ops`, `cmp`, `num`, `to_str`), and complete bindings
//! to the C standard library (`libc`).
//!
//! # Standard library injection and the Rust prelude
//!
//! `std` is imported at the topmost level of every crate by default, as
//! if the first line of each crate was
//!
//! extern mod std;
//!
//! This means that the contents of std can be accessed from any context
//! with the `std::` path prefix, as in `use std::vec`, `use std::task::spawn`,
//! etc.
//!
//! Additionally, `std` contains a `prelude` module that reexports many of the
//! most common types, traits and functions. The contents of the prelude are
//! imported into every *module* by default. Implicitly, all modules behave as if
//! they contained the following prologue:
//!
//! use std::prelude::*;
#[link(name = "std",
vers = "0.9-pre",
@ -97,6 +92,7 @@ pub mod linkhack {
pub mod prelude;
/* Primitive types */
#[path = "num/int_macros.rs"] mod int_macros;
@ -158,6 +154,7 @@ pub mod container;
pub mod default;
pub mod any;
/* Common data structures */
pub mod option;
@ -198,11 +195,13 @@ pub mod util;
pub mod routine;
pub mod mem;
/* Unsupported interfaces */
// Private APIs
pub mod unstable;
/* For internal use, not exported */
mod unicode;

View File

@ -8,11 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/*!
Functions for the unit type.
*/
//! Functions for the unit type.
#[cfg(not(test))]
use prelude::*;

View File

@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern:called `Result::unwrap()` on `Err` value: kitty
// error-pattern:called `Result::unwrap()` on `Err` value 'kitty'
use std::result;