From b8a5440b2de600c47ed9c9c3d7a376807b57a579 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 15 Jun 2011 12:46:30 -0700 Subject: [PATCH] stdlib: Add an either module Like Haskell's, with left and right tags, various conversion functions --- src/lib/either.rs | 64 +++++++++++++++++ src/lib/std.rc | 1 + src/test/run-pass/lib-either.rs | 117 ++++++++++++++++++++++++++++++++ 3 files changed, 182 insertions(+) create mode 100644 src/lib/either.rs create mode 100644 src/test/run-pass/lib-either.rs diff --git a/src/lib/either.rs b/src/lib/either.rs new file mode 100644 index 00000000000..12ccbb2bbfb --- /dev/null +++ b/src/lib/either.rs @@ -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: +// diff --git a/src/lib/std.rc b/src/lib/std.rc index 60cecd7cf68..26d36257bd5 100644 --- a/src/lib/std.rc +++ b/src/lib/std.rc @@ -22,6 +22,7 @@ mod task; // Utility modules. +mod either; mod option; mod util; diff --git a/src/test/run-pass/lib-either.rs b/src/test/run-pass/lib-either.rs new file mode 100644 index 00000000000..0ece8be64e9 --- /dev/null +++ b/src/test/run-pass/lib-either.rs @@ -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(); +} \ No newline at end of file