2012-08-13 19:11:33 -05:00
|
|
|
// NB: transitionary, de-mode-ing.
|
|
|
|
#[forbid(deprecated_mode)];
|
|
|
|
#[forbid(deprecated_pattern)];
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
//! A type that represents one of two alternatives
|
2011-12-13 18:25:51 -06:00
|
|
|
|
2012-03-16 17:14:37 -05:00
|
|
|
import result::result;
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// The either type
|
2012-08-14 18:54:13 -05:00
|
|
|
enum Either<T, U> {
|
|
|
|
Left(T),
|
|
|
|
Right(U)
|
2011-12-13 18:25:51 -06:00
|
|
|
}
|
|
|
|
|
2012-08-13 19:11:33 -05:00
|
|
|
fn either<T, U, V>(f_left: fn((&T)) -> V,
|
2012-08-14 18:54:13 -05:00
|
|
|
f_right: fn((&U)) -> V, value: &Either<T, U>) -> V {
|
2012-07-04 16:53:12 -05:00
|
|
|
/*!
|
|
|
|
* 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.
|
|
|
|
*/
|
2011-12-13 18:25:51 -06:00
|
|
|
|
2012-08-13 19:11:33 -05:00
|
|
|
match *value {
|
2012-08-14 18:54:13 -05:00
|
|
|
Left(ref l) => f_left(l),
|
|
|
|
Right(ref r) => f_right(r)
|
2012-08-03 21:59:04 -05:00
|
|
|
}
|
2011-12-13 18:25:51 -06:00
|
|
|
}
|
|
|
|
|
2012-08-14 18:54:13 -05:00
|
|
|
fn lefts<T: copy, U>(eithers: &[Either<T, U>]) -> ~[T] {
|
2012-07-04 16:53:12 -05:00
|
|
|
//! Extracts from a vector of either all the left values
|
2012-03-06 21:09:32 -06:00
|
|
|
|
2012-06-29 18:26:56 -05:00
|
|
|
let mut result: ~[T] = ~[];
|
2012-06-30 18:19:07 -05:00
|
|
|
for vec::each(eithers) |elt| {
|
2012-08-06 14:34:08 -05:00
|
|
|
match elt {
|
2012-08-14 18:54:13 -05:00
|
|
|
Left(l) => vec::push(result, l),
|
2012-08-03 21:59:04 -05:00
|
|
|
_ => { /* fallthrough */ }
|
|
|
|
}
|
2011-12-13 18:25:51 -06:00
|
|
|
}
|
2012-08-01 19:30:05 -05:00
|
|
|
return result;
|
2011-12-13 18:25:51 -06:00
|
|
|
}
|
|
|
|
|
2012-08-14 18:54:13 -05:00
|
|
|
fn rights<T, U: copy>(eithers: &[Either<T, U>]) -> ~[U] {
|
2012-07-04 16:53:12 -05:00
|
|
|
//! Extracts from a vector of either all the right values
|
2012-03-06 21:09:32 -06:00
|
|
|
|
2012-06-29 18:26:56 -05:00
|
|
|
let mut result: ~[U] = ~[];
|
2012-06-30 18:19:07 -05:00
|
|
|
for vec::each(eithers) |elt| {
|
2012-08-06 14:34:08 -05:00
|
|
|
match elt {
|
2012-08-14 18:54:13 -05:00
|
|
|
Right(r) => vec::push(result, r),
|
2012-08-03 21:59:04 -05:00
|
|
|
_ => { /* fallthrough */ }
|
|
|
|
}
|
2011-12-13 18:25:51 -06:00
|
|
|
}
|
2012-08-01 19:30:05 -05:00
|
|
|
return result;
|
2011-12-13 18:25:51 -06:00
|
|
|
}
|
|
|
|
|
2012-08-14 18:54:13 -05:00
|
|
|
fn partition<T: copy, U: copy>(eithers: &[Either<T, U>])
|
2012-06-29 18:26:56 -05:00
|
|
|
-> {lefts: ~[T], rights: ~[U]} {
|
2012-07-04 16:53:12 -05:00
|
|
|
/*!
|
|
|
|
* 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.
|
|
|
|
*/
|
2012-03-06 21:09:32 -06:00
|
|
|
|
2012-06-29 18:26:56 -05:00
|
|
|
let mut lefts: ~[T] = ~[];
|
|
|
|
let mut rights: ~[U] = ~[];
|
2012-06-30 18:19:07 -05:00
|
|
|
for vec::each(eithers) |elt| {
|
2012-08-06 14:34:08 -05:00
|
|
|
match elt {
|
2012-08-14 18:54:13 -05:00
|
|
|
Left(l) => vec::push(lefts, l),
|
|
|
|
Right(r) => vec::push(rights, r)
|
2012-06-27 17:21:50 -05:00
|
|
|
}
|
2011-12-13 18:25:51 -06:00
|
|
|
}
|
2012-08-01 19:30:05 -05:00
|
|
|
return {lefts: lefts, rights: rights};
|
2011-12-13 18:25:51 -06:00
|
|
|
}
|
|
|
|
|
2012-08-14 18:54:13 -05:00
|
|
|
pure fn flip<T: copy, U: copy>(eith: &Either<T, U>) -> Either<U, T> {
|
2012-07-04 16:53:12 -05:00
|
|
|
//! Flips between left and right of a given either
|
2012-03-06 21:09:32 -06:00
|
|
|
|
2012-08-13 19:11:33 -05:00
|
|
|
match *eith {
|
2012-08-14 18:54:13 -05:00
|
|
|
Right(r) => Left(r),
|
|
|
|
Left(l) => Right(l)
|
2011-12-16 09:31:35 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-14 18:54:13 -05:00
|
|
|
pure fn to_result<T: copy, U: copy>(eith: &Either<T, U>) -> result<U, T> {
|
2012-07-04 16:53:12 -05:00
|
|
|
/*!
|
|
|
|
* 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
|
|
|
|
*/
|
2012-03-06 21:09:32 -06:00
|
|
|
|
2012-08-13 19:11:33 -05:00
|
|
|
match *eith {
|
2012-08-14 18:54:13 -05:00
|
|
|
Right(r) => result::ok(r),
|
|
|
|
Left(l) => result::err(l)
|
2011-12-16 09:31:35 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-14 18:54:13 -05:00
|
|
|
pure fn is_left<T, U>(eith: &Either<T, U>) -> bool {
|
2012-07-04 16:53:12 -05:00
|
|
|
//! Checks whether the given value is a left
|
2012-03-06 21:09:32 -06:00
|
|
|
|
2012-08-14 18:54:13 -05:00
|
|
|
match *eith { Left(_) => true, _ => false }
|
2012-01-04 09:36:53 -06:00
|
|
|
}
|
|
|
|
|
2012-08-14 18:54:13 -05:00
|
|
|
pure fn is_right<T, U>(eith: &Either<T, U>) -> bool {
|
2012-07-04 16:53:12 -05:00
|
|
|
//! Checks whether the given value is a right
|
2012-03-06 21:09:32 -06:00
|
|
|
|
2012-08-14 18:54:13 -05:00
|
|
|
match *eith { Right(_) => true, _ => false }
|
2012-01-04 09:36:53 -06:00
|
|
|
}
|
|
|
|
|
2012-01-17 19:28:21 -06:00
|
|
|
#[test]
|
|
|
|
fn test_either_left() {
|
2012-08-14 18:54:13 -05:00
|
|
|
let val = Left(10);
|
2012-08-13 19:11:33 -05:00
|
|
|
fn f_left(x: &int) -> bool { *x == 10 }
|
|
|
|
fn f_right(_x: &uint) -> bool { false }
|
|
|
|
assert (either(f_left, f_right, &val));
|
2012-01-17 19:28:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_either_right() {
|
2012-08-14 18:54:13 -05:00
|
|
|
let val = Right(10u);
|
2012-08-13 19:11:33 -05:00
|
|
|
fn f_left(_x: &int) -> bool { false }
|
|
|
|
fn f_right(x: &uint) -> bool { *x == 10u }
|
|
|
|
assert (either(f_left, f_right, &val));
|
2012-01-17 19:28:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_lefts() {
|
2012-08-14 18:54:13 -05:00
|
|
|
let input = ~[Left(10), Right(11), Left(12), Right(13), Left(14)];
|
2012-01-17 19:28:21 -06:00
|
|
|
let result = lefts(input);
|
2012-06-29 18:26:56 -05:00
|
|
|
assert (result == ~[10, 12, 14]);
|
2012-01-17 19:28:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_lefts_none() {
|
2012-08-14 18:54:13 -05:00
|
|
|
let input: ~[Either<int, int>] = ~[Right(10), Right(10)];
|
2012-01-17 19:28:21 -06:00
|
|
|
let result = lefts(input);
|
|
|
|
assert (vec::len(result) == 0u);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_lefts_empty() {
|
2012-08-14 18:54:13 -05:00
|
|
|
let input: ~[Either<int, int>] = ~[];
|
2012-01-17 19:28:21 -06:00
|
|
|
let result = lefts(input);
|
|
|
|
assert (vec::len(result) == 0u);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_rights() {
|
2012-08-14 18:54:13 -05:00
|
|
|
let input = ~[Left(10), Right(11), Left(12), Right(13), Left(14)];
|
2012-01-17 19:28:21 -06:00
|
|
|
let result = rights(input);
|
2012-06-29 18:26:56 -05:00
|
|
|
assert (result == ~[11, 13]);
|
2012-01-17 19:28:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_rights_none() {
|
2012-08-14 18:54:13 -05:00
|
|
|
let input: ~[Either<int, int>] = ~[Left(10), Left(10)];
|
2012-01-17 19:28:21 -06:00
|
|
|
let result = rights(input);
|
|
|
|
assert (vec::len(result) == 0u);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_rights_empty() {
|
2012-08-14 18:54:13 -05:00
|
|
|
let input: ~[Either<int, int>] = ~[];
|
2012-01-17 19:28:21 -06:00
|
|
|
let result = rights(input);
|
|
|
|
assert (vec::len(result) == 0u);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_partition() {
|
2012-08-14 18:54:13 -05:00
|
|
|
let input = ~[Left(10), Right(11), Left(12), Right(13), Left(14)];
|
2012-01-17 19:28:21 -06:00
|
|
|
let result = partition(input);
|
|
|
|
assert (result.lefts[0] == 10);
|
|
|
|
assert (result.lefts[1] == 12);
|
|
|
|
assert (result.lefts[2] == 14);
|
|
|
|
assert (result.rights[0] == 11);
|
|
|
|
assert (result.rights[1] == 13);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_partition_no_lefts() {
|
2012-08-14 18:54:13 -05:00
|
|
|
let input: ~[Either<int, int>] = ~[Right(10), Right(11)];
|
2012-01-17 19:28:21 -06:00
|
|
|
let result = partition(input);
|
|
|
|
assert (vec::len(result.lefts) == 0u);
|
|
|
|
assert (vec::len(result.rights) == 2u);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_partition_no_rights() {
|
2012-08-14 18:54:13 -05:00
|
|
|
let input: ~[Either<int, int>] = ~[Left(10), Left(11)];
|
2012-01-17 19:28:21 -06:00
|
|
|
let result = partition(input);
|
|
|
|
assert (vec::len(result.lefts) == 2u);
|
|
|
|
assert (vec::len(result.rights) == 0u);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_partition_empty() {
|
2012-08-14 18:54:13 -05:00
|
|
|
let input: ~[Either<int, int>] = ~[];
|
2012-01-17 19:28:21 -06:00
|
|
|
let result = partition(input);
|
|
|
|
assert (vec::len(result.lefts) == 0u);
|
|
|
|
assert (vec::len(result.rights) == 0u);
|
|
|
|
}
|
2012-03-06 21:09:32 -06:00
|
|
|
|
|
|
|
//
|
|
|
|
// Local Variables:
|
|
|
|
// mode: rust
|
|
|
|
// fill-column: 78;
|
|
|
|
// indent-tabs-mode: nil
|
|
|
|
// c-basic-offset: 4
|
|
|
|
// buffer-file-coding-system: utf-8-unix
|
|
|
|
// End:
|
|
|
|
//
|