2012-03-06 21:09:32 -06:00
|
|
|
#[doc = "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-03-06 21:09:32 -06:00
|
|
|
#[doc = "The either type"]
|
2012-03-13 16:39:28 -05:00
|
|
|
enum either<T, U> {
|
2012-01-19 21:08:08 -06:00
|
|
|
left(T),
|
2012-01-19 21:29:21 -06:00
|
|
|
right(U)
|
2011-12-13 18:25:51 -06:00
|
|
|
}
|
|
|
|
|
2012-03-06 21:09:32 -06:00
|
|
|
fn either<T, U, V>(f_left: fn(T) -> V,
|
2012-03-13 16:39:28 -05:00
|
|
|
f_right: fn(U) -> V, value: either<T, U>) -> V {
|
2012-03-06 21:09:32 -06:00
|
|
|
#[doc = "
|
|
|
|
Applies a function based on the given either value
|
2011-12-13 18:25:51 -06:00
|
|
|
|
2012-03-06 21:09:32 -06:00
|
|
|
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
|
|
|
|
|
|
|
alt value { left(l) { f_left(l) } right(r) { f_right(r) } }
|
|
|
|
}
|
|
|
|
|
2012-06-25 22:00:46 -05:00
|
|
|
fn lefts<T: copy, U>(eithers: [either<T, U>]/~) -> [T]/~ {
|
2012-03-06 21:09:32 -06:00
|
|
|
#[doc = "Extracts from a vector of either all the left values"];
|
|
|
|
|
2012-06-25 22:00:46 -05:00
|
|
|
let mut result: [T]/~ = []/~;
|
2012-03-27 08:14:12 -05:00
|
|
|
for vec::each(eithers) {|elt|
|
2012-06-25 22:00:46 -05:00
|
|
|
alt elt { left(l) { result += [l]/~; } _ {/* fallthrough */ } }
|
2011-12-13 18:25:51 -06:00
|
|
|
}
|
|
|
|
ret result;
|
|
|
|
}
|
|
|
|
|
2012-06-25 22:00:46 -05:00
|
|
|
fn rights<T, U: copy>(eithers: [either<T, U>]/~) -> [U]/~ {
|
2012-03-06 21:09:32 -06:00
|
|
|
#[doc = "Extracts from a vector of either all the right values"];
|
|
|
|
|
2012-06-25 22:00:46 -05:00
|
|
|
let mut result: [U]/~ = []/~;
|
2012-03-27 08:14:12 -05:00
|
|
|
for vec::each(eithers) {|elt|
|
2012-06-25 22:00:46 -05:00
|
|
|
alt elt { right(r) { result += [r]/~; } _ {/* fallthrough */ } }
|
2011-12-13 18:25:51 -06:00
|
|
|
}
|
|
|
|
ret result;
|
|
|
|
}
|
|
|
|
|
2012-06-25 22:00:46 -05:00
|
|
|
fn partition<T: copy, U: copy>(eithers: [either<T, U>]/~)
|
|
|
|
-> {lefts: [T]/~, rights: [U]/~} {
|
2012-03-06 21:09:32 -06:00
|
|
|
#[doc = "
|
|
|
|
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-06-25 22:00:46 -05:00
|
|
|
let mut lefts: [T]/~ = []/~;
|
|
|
|
let mut rights: [U]/~ = []/~;
|
2012-03-27 08:14:12 -05:00
|
|
|
for vec::each(eithers) {|elt|
|
2012-06-25 22:00:46 -05:00
|
|
|
alt elt { left(l) { lefts += [l]/~; } right(r) { rights += [r]/~; } }
|
2011-12-13 18:25:51 -06:00
|
|
|
}
|
|
|
|
ret {lefts: lefts, rights: rights};
|
|
|
|
}
|
|
|
|
|
2012-03-13 16:39:28 -05:00
|
|
|
pure fn flip<T: copy, U: copy>(eith: either<T, U>) -> either<U, T> {
|
2012-03-06 21:09:32 -06:00
|
|
|
#[doc = "Flips between left and right of a given either"];
|
|
|
|
|
2011-12-16 09:31:35 -06:00
|
|
|
alt eith {
|
|
|
|
right(r) { left(r) }
|
|
|
|
left(l) { right(l) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-13 16:39:28 -05:00
|
|
|
pure fn to_result<T: copy, U: copy>(
|
|
|
|
eith: either<T, U>) -> result<U, T> {
|
2012-03-06 21:09:32 -06:00
|
|
|
#[doc = "
|
|
|
|
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
|
|
|
|
"];
|
|
|
|
|
2011-12-16 09:31:35 -06:00
|
|
|
alt eith {
|
|
|
|
right(r) { result::ok(r) }
|
|
|
|
left(l) { result::err(l) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-13 16:39:28 -05:00
|
|
|
pure fn is_left<T, U>(eith: either<T, U>) -> bool {
|
2012-03-06 21:09:32 -06:00
|
|
|
#[doc = "Checks whether the given value is a left"];
|
|
|
|
|
2012-01-04 09:36:53 -06:00
|
|
|
alt eith { left(_) { true } _ { false } }
|
|
|
|
}
|
|
|
|
|
2012-03-13 16:39:28 -05:00
|
|
|
pure fn is_right<T, U>(eith: either<T, U>) -> bool {
|
2012-03-06 21:09:32 -06:00
|
|
|
#[doc = "Checks whether the given value is a right"];
|
|
|
|
|
2012-01-04 09:36:53 -06:00
|
|
|
alt eith { right(_) { true } _ { false } }
|
|
|
|
}
|
|
|
|
|
2012-01-17 19:28:21 -06:00
|
|
|
#[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() {
|
2012-06-25 22:00:46 -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-25 22:00:46 -05:00
|
|
|
assert (result == [10, 12, 14]/~);
|
2012-01-17 19:28:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_lefts_none() {
|
2012-06-25 22:00:46 -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-06-25 22:00:46 -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-06-25 22:00:46 -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-25 22:00:46 -05:00
|
|
|
assert (result == [11, 13]/~);
|
2012-01-17 19:28:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_rights_none() {
|
2012-06-25 22:00:46 -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-06-25 22:00:46 -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-06-25 22:00:46 -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-06-25 22:00:46 -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-06-25 22:00:46 -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-06-25 22:00:46 -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:
|
|
|
|
//
|