Skip to content

Commit 68e5d8d

Browse files
committed
Merge pull request #2455 from erickt/master
Fleshing out result methods
2 parents 07db8c8 + ed5af70 commit 68e5d8d

File tree

3 files changed

+253
-10
lines changed

3 files changed

+253
-10
lines changed

src/libcore/result.rs

Lines changed: 138 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,79 @@ fn chain_err<T: copy, U: copy, V: copy>(
107107
}
108108
}
109109

110+
#[doc = "
111+
Call a function based on a previous result
112+
113+
If `res` is `ok` then the value is extracted and passed to `op` whereupon
114+
`op`s result is returned. if `res` is `err` then it is immediately returned.
115+
This function can be used to compose the results of two functions.
116+
117+
Example:
118+
119+
iter(read_file(file)) { |buf|
120+
print_buf(buf)
121+
}
122+
"]
123+
fn iter<T, E>(res: result<T, E>, f: fn(T)) {
124+
alt res {
125+
ok(t) { f(t) }
126+
err(_) { }
127+
}
128+
}
129+
130+
#[doc = "
131+
Call a function based on a previous result
132+
133+
If `res` is `err` then the value is extracted and passed to `op` whereupon
134+
`op`s result is returned. if `res` is `ok` then it is immediately returned.
135+
This function can be used to pass through a successful result while handling
136+
an error.
137+
"]
138+
fn iter_err<T, E>(res: result<T, E>, f: fn(E)) {
139+
alt res {
140+
ok(_) { }
141+
err(e) { f(e) }
142+
}
143+
}
144+
145+
#[doc = "
146+
Call a function based on a previous result
147+
148+
If `res` is `ok` then the value is extracted and passed to `op` whereupon
149+
`op`s result is wrapped in `ok` and returned. if `res` is `err` then it is
150+
immediately returned. This function can be used to compose the results of two
151+
functions.
152+
153+
Example:
154+
155+
let res = map(read_file(file)) { |buf|
156+
parse_buf(buf)
157+
}
158+
"]
159+
fn map<T, E: copy, U: copy>(res: result<T, E>, op: fn(T) -> U)
160+
-> result<U, E> {
161+
alt res {
162+
ok(t) { ok(op(t)) }
163+
err(e) { err(e) }
164+
}
165+
}
166+
167+
#[doc = "
168+
Call a function based on a previous result
169+
170+
If `res` is `err` then the value is extracted and passed to `op` whereupon
171+
`op`s result is wrapped in an `err` and returned. if `res` is `ok` then it is
172+
immediately returned. This function can be used to pass through a successful
173+
result while handling an error.
174+
"]
175+
fn map_err<T: copy, E, F: copy>(res: result<T, E>, op: fn(E) -> F)
176+
-> result<T, F> {
177+
alt res {
178+
ok(t) { ok(t) }
179+
err(e) { err(op(e)) }
180+
}
181+
}
182+
110183
impl extensions<T:copy, E:copy> for result<T,E> {
111184
fn get() -> T { get(self) }
112185

@@ -123,6 +196,34 @@ impl extensions<T:copy, E:copy> for result<T,E> {
123196
fn chain_err<F:copy>(op: fn(E) -> result<T,F>) -> result<T,F> {
124197
chain_err(self, op)
125198
}
199+
200+
fn iter(f: fn(T)) {
201+
alt self {
202+
ok(t) { f(t) }
203+
err(_) { }
204+
}
205+
}
206+
207+
fn iter_err(f: fn(E)) {
208+
alt self {
209+
ok(_) { }
210+
err(e) { f(e) }
211+
}
212+
}
213+
214+
fn map<U:copy>(op: fn(T) -> U) -> result<U,E> {
215+
alt self {
216+
ok(t) { ok(op(t)) }
217+
err(e) { err(e) }
218+
}
219+
}
220+
221+
fn map_err<F:copy>(op: fn(E) -> F) -> result<T,F> {
222+
alt self {
223+
ok(t) { ok(t) }
224+
err(e) { err(op(e)) }
225+
}
226+
}
126227
}
127228

128229
#[doc = "
@@ -142,7 +243,7 @@ checking for overflow:
142243
assert incd == [2u, 3u, 4u];
143244
}
144245
"]
145-
fn map<T,U:copy,V:copy>(
246+
fn map_vec<T,U:copy,V:copy>(
146247
ts: [T], op: fn(T) -> result<V,U>) -> result<[V],U> {
147248

148249
let mut vs: [V] = [];
@@ -177,7 +278,7 @@ length. While we do not often use preconditions in the standard
177278
library, a precondition is used here because result::t is generally
178279
used in 'careful' code contexts where it is both appropriate and easy
179280
to accommodate an error like the vectors being of different lengths."]
180-
fn map2<S,T,U:copy,V:copy>(ss: [S], ts: [T], op: fn(S,T) -> result<V,U>)
281+
fn map_vec2<S,T,U:copy,V:copy>(ss: [S], ts: [T], op: fn(S,T) -> result<V,U>)
181282
: vec::same_length(ss, ts) -> result<[V],U> {
182283

183284
let n = vec::len(ts);
@@ -199,8 +300,8 @@ Applies op to the pairwise elements from `ss` and `ts`, aborting on
199300
error. This could be implemented using `map2()` but it is more efficient
200301
on its own as no result vector is built.
201302
"]
202-
fn iter2<S,T,U:copy>(ss: [S], ts: [T],
203-
op: fn(S,T) -> result<(),U>)
303+
fn iter_vec2<S,T,U:copy>(ss: [S], ts: [T],
304+
op: fn(S,T) -> result<(),U>)
204305
: vec::same_length(ss, ts)
205306
-> result<(),U> {
206307

@@ -248,4 +349,37 @@ mod tests {
248349
fn chain_failure() {
249350
assert get_err(chain(op3(), op2)) == "sadface";
250351
}
352+
353+
#[test]
354+
fn test_impl_iter() {
355+
let mut valid = false;
356+
ok::<str, str>("a").iter { |_x| valid = true; };
357+
assert valid;
358+
359+
err::<str, str>("b").iter { |_x| valid = false; };
360+
assert valid;
361+
}
362+
363+
#[test]
364+
fn test_impl_iter_err() {
365+
let mut valid = true;
366+
ok::<str, str>("a").iter_err { |_x| valid = false; };
367+
assert valid;
368+
369+
valid = false;
370+
err::<str, str>("b").iter_err { |_x| valid = true; };
371+
assert valid;
372+
}
373+
374+
#[test]
375+
fn test_impl_map() {
376+
assert ok::<str, str>("a").map { |_x| "b" } == ok("b");
377+
assert err::<str, str>("a").map { |_x| "b" } == err("a");
378+
}
379+
380+
#[test]
381+
fn test_impl_map_err() {
382+
assert ok::<str, str>("a").map_err { |_x| "b" } == ok("a");
383+
assert err::<str, str>("a").map_err { |_x| "b" } == err("b");
384+
}
251385
}

src/libstd/json.rs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export to_str;
1616
export from_reader;
1717
export from_str;
1818
export eq;
19+
export to_json;
1920

2021
export num;
2122
export string;
@@ -498,6 +499,110 @@ fn eq(value0: json, value1: json) -> bool {
498499
}
499500
}
500501

502+
iface to_json { fn to_json() -> json; }
503+
504+
impl of to_json for json {
505+
fn to_json() -> json { self }
506+
}
507+
508+
impl of to_json for i8 {
509+
fn to_json() -> json { num(self as float) }
510+
}
511+
512+
impl of to_json for i16 {
513+
fn to_json() -> json { num(self as float) }
514+
}
515+
516+
impl of to_json for i32 {
517+
fn to_json() -> json { num(self as float) }
518+
}
519+
520+
impl of to_json for i64 {
521+
fn to_json() -> json { num(self as float) }
522+
}
523+
524+
impl of to_json for u8 {
525+
fn to_json() -> json { num(self as float) }
526+
}
527+
528+
impl of to_json for u16 {
529+
fn to_json() -> json { num(self as float) }
530+
}
531+
532+
impl of to_json for u32 {
533+
fn to_json() -> json { num(self as float) }
534+
}
535+
536+
impl of to_json for u64 {
537+
fn to_json() -> json { num(self as float) }
538+
}
539+
540+
impl of to_json for float {
541+
fn to_json() -> json { num(self) }
542+
}
543+
544+
impl of to_json for f32 {
545+
fn to_json() -> json { num(self as float) }
546+
}
547+
548+
impl of to_json for f64 {
549+
fn to_json() -> json { num(self as float) }
550+
}
551+
552+
impl of to_json for () {
553+
fn to_json() -> json { null }
554+
}
555+
556+
impl of to_json for bool {
557+
fn to_json() -> json { boolean(self) }
558+
}
559+
560+
impl of to_json for str {
561+
fn to_json() -> json { string(self) }
562+
}
563+
564+
impl <A: to_json copy, B: to_json copy> of to_json for (A, B) {
565+
fn to_json() -> json {
566+
let (a, b) = self;
567+
list([a.to_json(), b.to_json()])
568+
}
569+
}
570+
571+
impl <A: to_json copy, B: to_json copy, C: to_json copy>
572+
of to_json for (A, B, C) {
573+
fn to_json() -> json {
574+
let (a, b, c) = self;
575+
list([a.to_json(), b.to_json(), c.to_json()])
576+
}
577+
}
578+
579+
impl <A: to_json> of to_json for [A] {
580+
fn to_json() -> json { list(self.map { |elt| elt.to_json() }) }
581+
}
582+
583+
impl <A: to_json copy> of to_json for hashmap<str, A> {
584+
fn to_json() -> json {
585+
let d = map::str_hash();
586+
for self.each() { |key, value|
587+
d.insert(key, value.to_json());
588+
}
589+
dict(d)
590+
}
591+
}
592+
593+
impl <A: to_json> of to_json for option<A> {
594+
fn to_json() -> json {
595+
alt self {
596+
none { null }
597+
some(value) { value.to_json() }
598+
}
599+
}
600+
}
601+
602+
impl of to_str::to_str for json {
603+
fn to_str() -> str { to_str(self) }
604+
}
605+
501606
#[cfg(test)]
502607
mod tests {
503608
fn mk_dict(items: [(str, json)]) -> json {

src/rustc/middle/typeck/infer.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ import middle::ty::{ty_vid, tys_in_fn_ty, region_vid, vid};
151151
import syntax::{ast, ast_util};
152152
import syntax::ast::{ret_style};
153153
import util::ppaux::{ty_to_str, mt_to_str};
154-
import result::{result, extensions, ok, err, map, map2, iter2};
154+
import result::{result, extensions, ok, err, map_vec, map_vec2, iter_vec2};
155155
import ty::{mk_fn, type_is_bot};
156156
import check::regionmanip::{collect_bound_regions_in_tys,
157157
replace_bound_regions};
@@ -753,7 +753,7 @@ impl unify_methods for infer_ctxt {
753753
as: [@ty::type_constr], bs: [@ty::type_constr]) -> ures {
754754

755755
if check vec::same_length(as, bs) {
756-
iter2(as, bs) {|a,b|
756+
iter_vec2(as, bs) {|a,b|
757757
self.constrs(a, b)
758758
}
759759
} else {
@@ -1237,7 +1237,9 @@ fn super_tps<C:combine>(
12371237
// variance.
12381238

12391239
if check vec::same_length(as, bs) {
1240-
iter2(as, bs) {|a, b| self.infcx().eq_tys(a, b) }.then {||
1240+
iter_vec2(as, bs) {|a, b|
1241+
self.infcx().eq_tys(a, b)
1242+
}.then {||
12411243
ok(as)
12421244
}
12431245
} else {
@@ -1331,7 +1333,7 @@ fn super_fns<C:combine>(
13311333
self: C, a_args: [ty::arg], b_args: [ty::arg]) -> cres<[ty::arg]> {
13321334

13331335
if check vec::same_length(a_args, b_args) {
1334-
map2(a_args, b_args) {|a, b| self.args(a, b) }
1336+
map_vec2(a_args, b_args) {|a, b| self.args(a, b) }
13351337
} else {
13361338
err(ty::terr_arg_count)
13371339
}
@@ -1469,7 +1471,9 @@ fn super_tys<C:combine>(
14691471

14701472
(ty::ty_rec(as), ty::ty_rec(bs)) {
14711473
if check vec::same_length(as, bs) {
1472-
map2(as, bs) {|a,b| self.flds(a, b) }.chain {|flds|
1474+
map_vec2(as, bs) {|a,b|
1475+
self.flds(a, b)
1476+
}.chain {|flds|
14731477
ok(ty::mk_rec(tcx, flds))
14741478
}
14751479
} else {
@@ -1479,7 +1483,7 @@ fn super_tys<C:combine>(
14791483

14801484
(ty::ty_tup(as), ty::ty_tup(bs)) {
14811485
if check vec::same_length(as, bs) {
1482-
map2(as, bs) {|a, b| self.tys(a, b) }.chain {|ts|
1486+
map_vec2(as, bs) {|a, b| self.tys(a, b) }.chain {|ts|
14831487
ok(ty::mk_tup(tcx, ts))
14841488
}
14851489
} else {

0 commit comments

Comments
 (0)