Skip to content

Commit b8a5440

Browse files
committed
stdlib: Add an either module
Like Haskell's, with left and right tags, various conversion functions
1 parent 95bdedf commit b8a5440

File tree

3 files changed

+182
-0
lines changed

3 files changed

+182
-0
lines changed

src/lib/either.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import option;
2+
import option::some;
3+
import option::none;
4+
5+
tag t[T, U] {
6+
left(T);
7+
right(U);
8+
}
9+
10+
type operator[T, U] = fn(&T) -> U;
11+
12+
fn either[T, U, V](&operator[T, V] f_left,
13+
&operator[U, V] f_right,
14+
&t[T, U] value) -> V {
15+
alt (value) {
16+
case (left(?l)) { f_left(l) }
17+
case (right(?r)) { f_right(r) }
18+
}
19+
}
20+
21+
fn lefts[T, U](&vec[t[T, U]] eithers) -> vec[T] {
22+
let vec[T] result = [];
23+
for (t[T, U] elt in eithers) {
24+
alt (elt) {
25+
case (left(?l)) { result += [l] }
26+
case (_) { /* fallthrough */ }
27+
}
28+
}
29+
ret result;
30+
}
31+
32+
fn rights[T, U](&vec[t[T, U]] eithers) -> vec[U] {
33+
let vec[U] result = [];
34+
for (t[T, U] elt in eithers) {
35+
alt (elt) {
36+
case (right(?r)) { result += [r] }
37+
case (_) { /* fallthrough */ }
38+
}
39+
}
40+
ret result;
41+
}
42+
43+
fn partition[T, U](&vec[t[T, U]] eithers) -> tup(vec[T], vec[U]) {
44+
let vec[T] lefts = [];
45+
let vec[U] rights = [];
46+
for (t[T, U] elt in eithers) {
47+
alt (elt) {
48+
case (left(?l)) { lefts += [l] }
49+
case (right(?r)) { rights += [r] }
50+
}
51+
}
52+
ret tup(lefts, rights);
53+
}
54+
55+
//
56+
// Local Variables:
57+
// mode: rust
58+
// fill-column: 78;
59+
// indent-tabs-mode: nil
60+
// c-basic-offset: 4
61+
// buffer-file-coding-system: utf-8-unix
62+
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
63+
// End:
64+
//

src/lib/std.rc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ mod task;
2222

2323
// Utility modules.
2424

25+
mod either;
2526
mod option;
2627
mod util;
2728

src/test/run-pass/lib-either.rs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
// xfail-stage0
2+
3+
use std;
4+
import std::either::*;
5+
import std::vec::len;
6+
7+
fn test_either_left() {
8+
auto val = left(10);
9+
fn f_left(&int x) -> bool { x == 10 }
10+
fn f_right(&uint x) -> bool { false }
11+
assert (either(f_left, f_right, val));
12+
}
13+
14+
fn test_either_right() {
15+
auto val = right(10u);
16+
fn f_left(&int x) -> bool { false }
17+
fn f_right(&uint x) -> bool { x == 10u }
18+
assert (either(f_left, f_right, val));
19+
}
20+
21+
fn test_lefts() {
22+
auto input = [left(10),
23+
right(11),
24+
left(12),
25+
right(13),
26+
left(14)];
27+
auto result = lefts(input);
28+
assert (result == [10, 12, 14]);
29+
}
30+
31+
fn test_lefts_none() {
32+
let vec[t[int, int]] input = [right(10),
33+
right(10)];
34+
auto result = lefts(input);
35+
assert (len(result) == 0u);
36+
}
37+
38+
fn test_lefts_empty() {
39+
let vec[t[int, int]] input = [];
40+
auto result = lefts(input);
41+
assert (len(result) == 0u);
42+
}
43+
44+
fn test_rights() {
45+
auto input = [left(10),
46+
right(11),
47+
left(12),
48+
right(13),
49+
left(14)];
50+
auto result = rights(input);
51+
assert (result == [11, 13]);
52+
}
53+
54+
fn test_rights_none() {
55+
let vec[t[int, int]] input = [left(10),
56+
left(10)];
57+
auto result = rights(input);
58+
assert (len(result) == 0u);
59+
}
60+
61+
fn test_rights_empty() {
62+
let vec[t[int, int]] input = [];
63+
auto result = rights(input);
64+
assert (len(result) == 0u);
65+
}
66+
67+
fn test_partition() {
68+
auto input = [left(10),
69+
right(11),
70+
left(12),
71+
right(13),
72+
left(14)];
73+
auto result = partition(input);
74+
assert (result._0.(0) == 10);
75+
assert (result._0.(1) == 12);
76+
assert (result._0.(2) == 14);
77+
assert (result._1.(0) == 11);
78+
assert (result._1.(1) == 13);
79+
}
80+
81+
fn test_partition_no_lefts() {
82+
let vec[t[int, int]] input = [right(10),
83+
right(11)];
84+
auto result = partition(input);
85+
assert (len(result._0) == 0u);
86+
assert (len(result._1) == 2u);
87+
}
88+
89+
fn test_partition_no_rights() {
90+
let vec[t[int, int]] input = [left(10),
91+
left(11)];
92+
auto result = partition(input);
93+
assert (len(result._0) == 2u);
94+
assert (len(result._1) == 0u);
95+
}
96+
97+
fn test_partition_empty() {
98+
let vec[t[int, int]] input = [];
99+
auto result = partition(input);
100+
assert (len(result._0) == 0u);
101+
assert (len(result._1) == 0u);
102+
}
103+
104+
fn main() {
105+
test_either_left();
106+
test_either_right();
107+
test_lefts();
108+
test_lefts_none();
109+
test_lefts_empty();
110+
test_rights();
111+
test_rights_none();
112+
test_rights_empty();
113+
test_partition();
114+
test_partition_no_lefts();
115+
test_partition_no_rights();
116+
test_partition_empty();
117+
}

0 commit comments

Comments
 (0)