stdlib: Add result::chain for composing results

This commit is contained in:
Brian Anderson 2011-10-28 18:09:48 -07:00
parent c1092fb6d8
commit 2b62a80202
3 changed files with 49 additions and 8 deletions

View File

@ -19,11 +19,11 @@ tag t<T, U> {
*/ */
ok(T); ok(T);
/* /*
Variant: error Variant: err
Contains the error value Contains the error value
*/ */
error(U); err(U);
} }
/* Section: Operations */ /* Section: Operations */
@ -40,14 +40,14 @@ If the result is an error
fn get<T, U>(res: t<T, U>) -> T { fn get<T, U>(res: t<T, U>) -> T {
alt res { alt res {
ok(t) { t } ok(t) { t }
error(_) { err(_) {
fail "get called on error result"; fail "get called on error result";
} }
} }
} }
/* /*
Function: get Function: get_err
Get the value out of an error result Get the value out of an error result
@ -55,9 +55,9 @@ Failure:
If the result is not an error If the result is not an error
*/ */
fn get_error<T, U>(res: t<T, U>) -> U { fn get_err<T, U>(res: t<T, U>) -> U {
alt res { alt res {
error(u) { u } err(u) { u }
ok(_) { ok(_) {
fail "get_error called on ok result"; fail "get_error called on ok result";
} }
@ -72,7 +72,7 @@ Returns true if the result is <ok>
fn success<T, U>(res: t<T, U>) -> bool { fn success<T, U>(res: t<T, U>) -> bool {
alt res { alt res {
ok(_) { true } ok(_) { true }
error(_) { false } err(_) { false }
} }
} }
@ -83,4 +83,27 @@ Returns true if the result is <error>
*/ */
fn failure<T, U>(res: t<T, U>) -> bool { fn failure<T, U>(res: t<T, U>) -> bool {
!success(res) !success(res)
} }
/*
Function: chain
Call a function based on a previous result
If `res` is <ok> then the value is extracted and passed to `op` whereupon
`op`s result is returned. if `res` is <err> then it is immediately returned.
This function can be used to compose the results of two functions.
Example:
> let res = chain(read_file(file), { |buf]
> ok(parse_buf(buf))
> })
*/
fn chain<T, U, V>(res: t<T, V>, op: block(T) -> t<U, V>) -> t<U, V> {
alt res {
ok(t) { op(t) }
err(e) { err(e) }
}
}

View File

@ -0,0 +1,17 @@
import std::result;
fn op1() -> result::t<int, str> { result::ok(666) }
fn op2(&&i: int) -> result::t<uint, str> { result::ok(i as uint + 1u) }
fn op3() -> result::t<int, str> { result::err("sadface") }
#[test]
fn chain_success() {
assert result::get(result::chain(op1(), op2)) == 667u;
}
#[test]
fn chain_failure() {
assert result::get_err(result::chain(op3(), op2)) == "sadface";
}

View File

@ -31,6 +31,7 @@ mod test;
mod uint; mod uint;
mod float; mod float;
mod math; mod math;
mod result;
// Local Variables: // Local Variables:
// mode: rust // mode: rust