rust/src/libcore/either.rs
2012-01-23 19:06:33 -08:00

226 lines
4.8 KiB
Rust

/*
Module: either
A type that represents one of two alternatives
*/
/*
Tag: t
The either type
*/
enum t<T, U> {
/* Variant: left */
left(T),
/* Variant: right */
right(U)
}
/* Section: Operations */
/*
Function: either
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.
*/
fn either<T, U,
V>(f_left: fn(T) -> V, f_right: fn(U) -> V, value: t<T, U>) ->
V {
alt value { left(l) { f_left(l) } right(r) { f_right(r) } }
}
/*
Function: lefts
Extracts from a vector of either all the left values.
*/
fn lefts<T: copy, U>(eithers: [t<T, U>]) -> [T] {
let result: [T] = [];
for elt: t<T, U> in eithers {
alt elt { left(l) { result += [l]; } _ {/* fallthrough */ } }
}
ret result;
}
/*
Function: rights
Extracts from a vector of either all the right values
*/
fn rights<T, U: copy>(eithers: [t<T, U>]) -> [U] {
let result: [U] = [];
for elt: t<T, U> in eithers {
alt elt { right(r) { result += [r]; } _ {/* fallthrough */ } }
}
ret result;
}
/*
Function: partition
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.
*/
fn partition<T: copy, U: copy>(eithers: [t<T, U>])
-> {lefts: [T], rights: [U]} {
let lefts: [T] = [];
let rights: [U] = [];
for elt: t<T, U> in eithers {
alt elt { left(l) { lefts += [l]; } right(r) { rights += [r]; } }
}
ret {lefts: lefts, rights: rights};
}
/*
Function: flip
Flips between left and right of a given either
*/
pure fn flip<T: copy, U: copy>(eith: t<T, U>) -> t<U, T> {
alt eith {
right(r) { left(r) }
left(l) { right(l) }
}
}
/*
Function: to_result
Converts either::t to a result::t, making the "right" choice
an ok result, and the "left" choice a fail
*/
pure fn to_result<T: copy, U: copy>(eith: t<T, U>) -> result::t<U, T> {
alt eith {
right(r) { result::ok(r) }
left(l) { result::err(l) }
}
}
/*
Function: is_left
Checks whether the given value is a left
*/
pure fn is_left<T, U>(eith: t<T, U>) -> bool {
alt eith { left(_) { true } _ { false } }
}
/*
Function: is_left
Checks whether the given value is a right
*/
pure fn is_right<T, U>(eith: t<T, U>) -> bool {
alt eith { right(_) { true } _ { false } }
}
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//
#[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 (result == [10, 12, 14]);
}
#[test]
fn test_lefts_none() {
let input: [t<int, int>] = [right(10), right(10)];
let result = lefts(input);
assert (vec::len(result) == 0u);
}
#[test]
fn test_lefts_empty() {
let input: [t<int, int>] = [];
let result = lefts(input);
assert (vec::len(result) == 0u);
}
#[test]
fn test_rights() {
let input = [left(10), right(11), left(12), right(13), left(14)];
let result = rights(input);
assert (result == [11, 13]);
}
#[test]
fn test_rights_none() {
let input: [t<int, int>] = [left(10), left(10)];
let result = rights(input);
assert (vec::len(result) == 0u);
}
#[test]
fn test_rights_empty() {
let input: [t<int, int>] = [];
let result = rights(input);
assert (vec::len(result) == 0u);
}
#[test]
fn test_partition() {
let input = [left(10), right(11), left(12), right(13), left(14)];
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() {
let input: [t<int, int>] = [right(10), right(11)];
let result = partition(input);
assert (vec::len(result.lefts) == 0u);
assert (vec::len(result.rights) == 2u);
}
#[test]
fn test_partition_no_rights() {
let input: [t<int, int>] = [left(10), left(11)];
let result = partition(input);
assert (vec::len(result.lefts) == 2u);
assert (vec::len(result.rights) == 0u);
}
#[test]
fn test_partition_empty() {
let input: [t<int, int>] = [];
let result = partition(input);
assert (vec::len(result.lefts) == 0u);
assert (vec::len(result.rights) == 0u);
}