diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 18d78520bf5b3..3c6622ba69dd9 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -107,6 +107,79 @@ fn chain_err( } } +#[doc = " +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: + + iter(read_file(file)) { |buf| + print_buf(buf) + } +"] +fn iter(res: result, f: fn(T)) { + alt res { + ok(t) { f(t) } + err(_) { } + } +} + +#[doc = " +Call a function based on a previous result + +If `res` is `err` then the value is extracted and passed to `op` whereupon +`op`s result is returned. if `res` is `ok` then it is immediately returned. +This function can be used to pass through a successful result while handling +an error. +"] +fn iter_err(res: result, f: fn(E)) { + alt res { + ok(_) { } + err(e) { f(e) } + } +} + +#[doc = " +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 wrapped in `ok` and 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 = map(read_file(file)) { |buf| + parse_buf(buf) + } +"] +fn map(res: result, op: fn(T) -> U) + -> result { + alt res { + ok(t) { ok(op(t)) } + err(e) { err(e) } + } +} + +#[doc = " +Call a function based on a previous result + +If `res` is `err` then the value is extracted and passed to `op` whereupon +`op`s result is wrapped in an `err` and returned. if `res` is `ok` then it is +immediately returned. This function can be used to pass through a successful +result while handling an error. +"] +fn map_err(res: result, op: fn(E) -> F) + -> result { + alt res { + ok(t) { ok(t) } + err(e) { err(op(e)) } + } +} + impl extensions for result { fn get() -> T { get(self) } @@ -123,6 +196,34 @@ impl extensions for result { fn chain_err(op: fn(E) -> result) -> result { chain_err(self, op) } + + fn iter(f: fn(T)) { + alt self { + ok(t) { f(t) } + err(_) { } + } + } + + fn iter_err(f: fn(E)) { + alt self { + ok(_) { } + err(e) { f(e) } + } + } + + fn map(op: fn(T) -> U) -> result { + alt self { + ok(t) { ok(op(t)) } + err(e) { err(e) } + } + } + + fn map_err(op: fn(E) -> F) -> result { + alt self { + ok(t) { ok(t) } + err(e) { err(op(e)) } + } + } } #[doc = " @@ -142,7 +243,7 @@ checking for overflow: assert incd == [2u, 3u, 4u]; } "] -fn map( +fn map_vec( ts: [T], op: fn(T) -> result) -> result<[V],U> { let mut vs: [V] = []; @@ -177,7 +278,7 @@ length. While we do not often use preconditions in the standard library, a precondition is used here because result::t is generally used in 'careful' code contexts where it is both appropriate and easy to accommodate an error like the vectors being of different lengths."] -fn map2(ss: [S], ts: [T], op: fn(S,T) -> result) +fn map_vec2(ss: [S], ts: [T], op: fn(S,T) -> result) : vec::same_length(ss, ts) -> result<[V],U> { let n = vec::len(ts); @@ -199,8 +300,8 @@ Applies op to the pairwise elements from `ss` and `ts`, aborting on error. This could be implemented using `map2()` but it is more efficient on its own as no result vector is built. "] -fn iter2(ss: [S], ts: [T], - op: fn(S,T) -> result<(),U>) +fn iter_vec2(ss: [S], ts: [T], + op: fn(S,T) -> result<(),U>) : vec::same_length(ss, ts) -> result<(),U> { @@ -248,4 +349,37 @@ mod tests { fn chain_failure() { assert get_err(chain(op3(), op2)) == "sadface"; } + + #[test] + fn test_impl_iter() { + let mut valid = false; + ok::("a").iter { |_x| valid = true; }; + assert valid; + + err::("b").iter { |_x| valid = false; }; + assert valid; + } + + #[test] + fn test_impl_iter_err() { + let mut valid = true; + ok::("a").iter_err { |_x| valid = false; }; + assert valid; + + valid = false; + err::("b").iter_err { |_x| valid = true; }; + assert valid; + } + + #[test] + fn test_impl_map() { + assert ok::("a").map { |_x| "b" } == ok("b"); + assert err::("a").map { |_x| "b" } == err("a"); + } + + #[test] + fn test_impl_map_err() { + assert ok::("a").map_err { |_x| "b" } == ok("a"); + assert err::("a").map_err { |_x| "b" } == err("b"); + } } diff --git a/src/libstd/json.rs b/src/libstd/json.rs index 82a8b5d9e8af8..5d9427c72b860 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -16,6 +16,7 @@ export to_str; export from_reader; export from_str; export eq; +export to_json; export num; export string; @@ -498,6 +499,110 @@ fn eq(value0: json, value1: json) -> bool { } } +iface to_json { fn to_json() -> json; } + +impl of to_json for json { + fn to_json() -> json { self } +} + +impl of to_json for i8 { + fn to_json() -> json { num(self as float) } +} + +impl of to_json for i16 { + fn to_json() -> json { num(self as float) } +} + +impl of to_json for i32 { + fn to_json() -> json { num(self as float) } +} + +impl of to_json for i64 { + fn to_json() -> json { num(self as float) } +} + +impl of to_json for u8 { + fn to_json() -> json { num(self as float) } +} + +impl of to_json for u16 { + fn to_json() -> json { num(self as float) } +} + +impl of to_json for u32 { + fn to_json() -> json { num(self as float) } +} + +impl of to_json for u64 { + fn to_json() -> json { num(self as float) } +} + +impl of to_json for float { + fn to_json() -> json { num(self) } +} + +impl of to_json for f32 { + fn to_json() -> json { num(self as float) } +} + +impl of to_json for f64 { + fn to_json() -> json { num(self as float) } +} + +impl of to_json for () { + fn to_json() -> json { null } +} + +impl of to_json for bool { + fn to_json() -> json { boolean(self) } +} + +impl of to_json for str { + fn to_json() -> json { string(self) } +} + +impl of to_json for (A, B) { + fn to_json() -> json { + let (a, b) = self; + list([a.to_json(), b.to_json()]) + } +} + +impl + of to_json for (A, B, C) { + fn to_json() -> json { + let (a, b, c) = self; + list([a.to_json(), b.to_json(), c.to_json()]) + } +} + +impl of to_json for [A] { + fn to_json() -> json { list(self.map { |elt| elt.to_json() }) } +} + +impl of to_json for hashmap { + fn to_json() -> json { + let d = map::str_hash(); + for self.each() { |key, value| + d.insert(key, value.to_json()); + } + dict(d) + } +} + +impl of to_json for option { + fn to_json() -> json { + alt self { + none { null } + some(value) { value.to_json() } + } + } +} + +impl of to_str::to_str for json { + fn to_str() -> str { to_str(self) } +} + #[cfg(test)] mod tests { fn mk_dict(items: [(str, json)]) -> json { diff --git a/src/rustc/middle/typeck/infer.rs b/src/rustc/middle/typeck/infer.rs index 02349614e55e5..1f4d479671c2c 100644 --- a/src/rustc/middle/typeck/infer.rs +++ b/src/rustc/middle/typeck/infer.rs @@ -151,7 +151,7 @@ import middle::ty::{ty_vid, tys_in_fn_ty, region_vid, vid}; import syntax::{ast, ast_util}; import syntax::ast::{ret_style}; import util::ppaux::{ty_to_str, mt_to_str}; -import result::{result, extensions, ok, err, map, map2, iter2}; +import result::{result, extensions, ok, err, map_vec, map_vec2, iter_vec2}; import ty::{mk_fn, type_is_bot}; import check::regionmanip::{collect_bound_regions_in_tys, replace_bound_regions}; @@ -753,7 +753,7 @@ impl unify_methods for infer_ctxt { as: [@ty::type_constr], bs: [@ty::type_constr]) -> ures { if check vec::same_length(as, bs) { - iter2(as, bs) {|a,b| + iter_vec2(as, bs) {|a,b| self.constrs(a, b) } } else { @@ -1237,7 +1237,9 @@ fn super_tps( // variance. if check vec::same_length(as, bs) { - iter2(as, bs) {|a, b| self.infcx().eq_tys(a, b) }.then {|| + iter_vec2(as, bs) {|a, b| + self.infcx().eq_tys(a, b) + }.then {|| ok(as) } } else { @@ -1331,7 +1333,7 @@ fn super_fns( self: C, a_args: [ty::arg], b_args: [ty::arg]) -> cres<[ty::arg]> { if check vec::same_length(a_args, b_args) { - map2(a_args, b_args) {|a, b| self.args(a, b) } + map_vec2(a_args, b_args) {|a, b| self.args(a, b) } } else { err(ty::terr_arg_count) } @@ -1469,7 +1471,9 @@ fn super_tys( (ty::ty_rec(as), ty::ty_rec(bs)) { if check vec::same_length(as, bs) { - map2(as, bs) {|a,b| self.flds(a, b) }.chain {|flds| + map_vec2(as, bs) {|a,b| + self.flds(a, b) + }.chain {|flds| ok(ty::mk_rec(tcx, flds)) } } else { @@ -1479,7 +1483,7 @@ fn super_tys( (ty::ty_tup(as), ty::ty_tup(bs)) { if check vec::same_length(as, bs) { - map2(as, bs) {|a, b| self.tys(a, b) }.chain {|ts| + map_vec2(as, bs) {|a, b| self.tys(a, b) }.chain {|ts| ok(ty::mk_tup(tcx, ts)) } } else {