stdlib: Add an either module
Like Haskell's, with left and right tags, various conversion functions
This commit is contained in:
parent
95bdedf12d
commit
b8a5440b2d
3 changed files with 182 additions and 0 deletions
64
src/lib/either.rs
Normal file
64
src/lib/either.rs
Normal file
|
@ -0,0 +1,64 @@
|
|||
import option;
|
||||
import option::some;
|
||||
import option::none;
|
||||
|
||||
tag t[T, U] {
|
||||
left(T);
|
||||
right(U);
|
||||
}
|
||||
|
||||
type operator[T, U] = fn(&T) -> U;
|
||||
|
||||
fn either[T, U, V](&operator[T, V] f_left,
|
||||
&operator[U, V] f_right,
|
||||
&t[T, U] value) -> V {
|
||||
alt (value) {
|
||||
case (left(?l)) { f_left(l) }
|
||||
case (right(?r)) { f_right(r) }
|
||||
}
|
||||
}
|
||||
|
||||
fn lefts[T, U](&vec[t[T, U]] eithers) -> vec[T] {
|
||||
let vec[T] result = [];
|
||||
for (t[T, U] elt in eithers) {
|
||||
alt (elt) {
|
||||
case (left(?l)) { result += [l] }
|
||||
case (_) { /* fallthrough */ }
|
||||
}
|
||||
}
|
||||
ret result;
|
||||
}
|
||||
|
||||
fn rights[T, U](&vec[t[T, U]] eithers) -> vec[U] {
|
||||
let vec[U] result = [];
|
||||
for (t[T, U] elt in eithers) {
|
||||
alt (elt) {
|
||||
case (right(?r)) { result += [r] }
|
||||
case (_) { /* fallthrough */ }
|
||||
}
|
||||
}
|
||||
ret result;
|
||||
}
|
||||
|
||||
fn partition[T, U](&vec[t[T, U]] eithers) -> tup(vec[T], vec[U]) {
|
||||
let vec[T] lefts = [];
|
||||
let vec[U] rights = [];
|
||||
for (t[T, U] elt in eithers) {
|
||||
alt (elt) {
|
||||
case (left(?l)) { lefts += [l] }
|
||||
case (right(?r)) { rights += [r] }
|
||||
}
|
||||
}
|
||||
ret tup(lefts, rights);
|
||||
}
|
||||
|
||||
//
|
||||
// Local Variables:
|
||||
// mode: rust
|
||||
// fill-column: 78;
|
||||
// indent-tabs-mode: nil
|
||||
// c-basic-offset: 4
|
||||
// buffer-file-coding-system: utf-8-unix
|
||||
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
|
||||
// End:
|
||||
//
|
|
@ -22,6 +22,7 @@ mod task;
|
|||
|
||||
// Utility modules.
|
||||
|
||||
mod either;
|
||||
mod option;
|
||||
mod util;
|
||||
|
||||
|
|
117
src/test/run-pass/lib-either.rs
Normal file
117
src/test/run-pass/lib-either.rs
Normal file
|
@ -0,0 +1,117 @@
|
|||
// xfail-stage0
|
||||
|
||||
use std;
|
||||
import std::either::*;
|
||||
import std::vec::len;
|
||||
|
||||
fn test_either_left() {
|
||||
auto val = left(10);
|
||||
fn f_left(&int x) -> bool { x == 10 }
|
||||
fn f_right(&uint x) -> bool { false }
|
||||
assert (either(f_left, f_right, val));
|
||||
}
|
||||
|
||||
fn test_either_right() {
|
||||
auto val = right(10u);
|
||||
fn f_left(&int x) -> bool { false }
|
||||
fn f_right(&uint x) -> bool { x == 10u }
|
||||
assert (either(f_left, f_right, val));
|
||||
}
|
||||
|
||||
fn test_lefts() {
|
||||
auto input = [left(10),
|
||||
right(11),
|
||||
left(12),
|
||||
right(13),
|
||||
left(14)];
|
||||
auto result = lefts(input);
|
||||
assert (result == [10, 12, 14]);
|
||||
}
|
||||
|
||||
fn test_lefts_none() {
|
||||
let vec[t[int, int]] input = [right(10),
|
||||
right(10)];
|
||||
auto result = lefts(input);
|
||||
assert (len(result) == 0u);
|
||||
}
|
||||
|
||||
fn test_lefts_empty() {
|
||||
let vec[t[int, int]] input = [];
|
||||
auto result = lefts(input);
|
||||
assert (len(result) == 0u);
|
||||
}
|
||||
|
||||
fn test_rights() {
|
||||
auto input = [left(10),
|
||||
right(11),
|
||||
left(12),
|
||||
right(13),
|
||||
left(14)];
|
||||
auto result = rights(input);
|
||||
assert (result == [11, 13]);
|
||||
}
|
||||
|
||||
fn test_rights_none() {
|
||||
let vec[t[int, int]] input = [left(10),
|
||||
left(10)];
|
||||
auto result = rights(input);
|
||||
assert (len(result) == 0u);
|
||||
}
|
||||
|
||||
fn test_rights_empty() {
|
||||
let vec[t[int, int]] input = [];
|
||||
auto result = rights(input);
|
||||
assert (len(result) == 0u);
|
||||
}
|
||||
|
||||
fn test_partition() {
|
||||
auto input = [left(10),
|
||||
right(11),
|
||||
left(12),
|
||||
right(13),
|
||||
left(14)];
|
||||
auto result = partition(input);
|
||||
assert (result._0.(0) == 10);
|
||||
assert (result._0.(1) == 12);
|
||||
assert (result._0.(2) == 14);
|
||||
assert (result._1.(0) == 11);
|
||||
assert (result._1.(1) == 13);
|
||||
}
|
||||
|
||||
fn test_partition_no_lefts() {
|
||||
let vec[t[int, int]] input = [right(10),
|
||||
right(11)];
|
||||
auto result = partition(input);
|
||||
assert (len(result._0) == 0u);
|
||||
assert (len(result._1) == 2u);
|
||||
}
|
||||
|
||||
fn test_partition_no_rights() {
|
||||
let vec[t[int, int]] input = [left(10),
|
||||
left(11)];
|
||||
auto result = partition(input);
|
||||
assert (len(result._0) == 2u);
|
||||
assert (len(result._1) == 0u);
|
||||
}
|
||||
|
||||
fn test_partition_empty() {
|
||||
let vec[t[int, int]] input = [];
|
||||
auto result = partition(input);
|
||||
assert (len(result._0) == 0u);
|
||||
assert (len(result._1) == 0u);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test_either_left();
|
||||
test_either_right();
|
||||
test_lefts();
|
||||
test_lefts_none();
|
||||
test_lefts_empty();
|
||||
test_rights();
|
||||
test_rights_none();
|
||||
test_rights_empty();
|
||||
test_partition();
|
||||
test_partition_no_lefts();
|
||||
test_partition_no_rights();
|
||||
test_partition_empty();
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue