Skip to content

Commit 72b50e7

Browse files
committed
auto merge of #8526 : blake2-ppc/rust/either-result, r=catamorphism
Retry of PR #8471 Replace the remaining functions marked for issue #8228 with similar functions that are iterator-based. Change `either::{lefts, rights}` to be iterator-filtering instead of returning a vector. Replace `map_vec`, `map_vec2`, `iter_vec2` in std::result with three functions: * `result::collect` gathers `Iterator<Result<V, U>>` to `Result<~[V], U>` * `result::fold` folds `Iterator<Result<T, E>>` to `Result<V, E>` * `result::fold_` folds `Iterator<Result<T, E>>` to `Result<(), E>`
2 parents 92af0db + 88c1491 commit 72b50e7

File tree

5 files changed

+130
-103
lines changed

5 files changed

+130
-103
lines changed

src/librustc/metadata/creader.rs

+3-11
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ pub fn read_crates(diag: @mut span_handler,
5757
warn_if_multiple_versions(e, diag, *e.crate_cache);
5858
}
5959

60+
#[deriving(Clone)]
6061
struct cache_entry {
6162
cnum: int,
6263
span: span,
@@ -76,22 +77,13 @@ fn dump_crates(crate_cache: &[cache_entry]) {
7677
fn warn_if_multiple_versions(e: @mut Env,
7778
diag: @mut span_handler,
7879
crate_cache: &[cache_entry]) {
79-
use std::either::*;
80-
8180
if crate_cache.len() != 0u {
8281
let name = loader::crate_name_from_metas(
8382
*crate_cache[crate_cache.len() - 1].metas
8483
);
8584

86-
let vec: ~[Either<cache_entry, cache_entry>] = crate_cache.iter().map(|&entry| {
87-
let othername = loader::crate_name_from_metas(*entry.metas);
88-
if name == othername {
89-
Left(entry)
90-
} else {
91-
Right(entry)
92-
}
93-
}).collect();
94-
let (matches, non_matches) = partition(vec);
85+
let (matches, non_matches) = crate_cache.partitioned(|entry|
86+
name == loader::crate_name_from_metas(*entry.metas));
9587

9688
assert!(!matches.is_empty());
9789

src/librustc/middle/typeck/infer/combine.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ use middle::typeck::infer::{InferCtxt, cres, ures};
6868
use middle::typeck::infer::{TypeTrace};
6969
use util::common::indent;
7070

71-
use std::result::{iter_vec2, map_vec2};
71+
use std::result;
7272
use std::vec;
7373
use syntax::ast::{Onceness, purity};
7474
use syntax::ast;
@@ -275,9 +275,9 @@ pub fn super_tps<C:Combine>(
275275
// variance.
276276

277277
if vec::same_length(as_, bs) {
278-
iter_vec2(as_, bs, |a, b| {
279-
eq_tys(this, *a, *b)
280-
}).then(|| Ok(as_.to_owned()) )
278+
result::fold_(as_.iter().zip(bs.iter())
279+
.map(|(a, b)| eq_tys(this, *a, *b)))
280+
.then(|| Ok(as_.to_owned()))
281281
} else {
282282
Err(ty::terr_ty_param_size(
283283
expected_found(this, as_.len(), bs.len())))
@@ -427,7 +427,8 @@ pub fn super_fn_sigs<C:Combine>(
427427
{
428428
fn argvecs<C:Combine>(this: &C, a_args: &[ty::t], b_args: &[ty::t]) -> cres<~[ty::t]> {
429429
if vec::same_length(a_args, b_args) {
430-
map_vec2(a_args, b_args, |a, b| this.args(*a, *b))
430+
result::collect(a_args.iter().zip(b_args.iter())
431+
.map(|(a, b)| this.args(*a, *b)))
431432
} else {
432433
Err(ty::terr_arg_count)
433434
}
@@ -586,8 +587,9 @@ pub fn super_tys<C:Combine>(
586587

587588
(&ty::ty_tup(ref as_), &ty::ty_tup(ref bs)) => {
588589
if as_.len() == bs.len() {
589-
map_vec2(*as_, *bs, |a, b| this.tys(*a, *b) )
590-
.chain(|ts| Ok(ty::mk_tup(tcx, ts)) )
590+
result::collect(as_.iter().zip(bs.iter())
591+
.map(|(a, b)| this.tys(*a, *b)))
592+
.chain(|ts| Ok(ty::mk_tup(tcx, ts)) )
591593
} else {
592594
Err(ty::terr_tuple_size(
593595
expected_found(this, as_.len(), bs.len())))

src/libstd/either.rs

+31-27
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use option::{Some, None};
1616
use clone::Clone;
1717
use container::Container;
1818
use cmp::Eq;
19-
use iterator::Iterator;
19+
use iterator::{Iterator, FilterMap};
2020
use result::Result;
2121
use result;
2222
use str::StrSlice;
@@ -116,40 +116,44 @@ impl<L, R> Either<L, R> {
116116
}
117117
}
118118

119-
// FIXME: #8228 Replaceable by an external iterator?
120-
/// Extracts from a vector of either all the left values
121-
pub fn lefts<L: Clone, R>(eithers: &[Either<L, R>]) -> ~[L] {
122-
do vec::build_sized(eithers.len()) |push| {
123-
for elt in eithers.iter() {
124-
match *elt {
125-
Left(ref l) => { push((*l).clone()); }
126-
_ => { /* fallthrough */ }
127-
}
119+
/// An iterator yielding the `Left` values of its source
120+
pub type Lefts<L, R, Iter> = FilterMap<'static, Either<L, R>, L, Iter>;
121+
122+
/// An iterator yielding the `Right` values of its source
123+
pub type Rights<L, R, Iter> = FilterMap<'static, Either<L, R>, R, Iter>;
124+
125+
/// Extracts all the left values
126+
pub fn lefts<L, R, Iter: Iterator<Either<L, R>>>(eithers: Iter)
127+
-> Lefts<L, R, Iter> {
128+
do eithers.filter_map |elt| {
129+
match elt {
130+
Left(x) => Some(x),
131+
_ => None,
128132
}
129133
}
130134
}
131135

132-
// FIXME: #8228 Replaceable by an external iterator?
133-
/// Extracts from a vector of either all the right values
134-
pub fn rights<L, R: Clone>(eithers: &[Either<L, R>]) -> ~[R] {
135-
do vec::build_sized(eithers.len()) |push| {
136-
for elt in eithers.iter() {
137-
match *elt {
138-
Right(ref r) => { push((*r).clone()); }
139-
_ => { /* fallthrough */ }
140-
}
136+
/// Extracts all the right values
137+
pub fn rights<L, R, Iter: Iterator<Either<L, R>>>(eithers: Iter)
138+
-> Rights<L, R, Iter> {
139+
do eithers.filter_map |elt| {
140+
match elt {
141+
Right(x) => Some(x),
142+
_ => None,
141143
}
142144
}
143145
}
144146

147+
145148
// FIXME: #8228 Replaceable by an external iterator?
146149
/// Extracts from a vector of either all the left values and right values
147150
///
148151
/// Returns a structure containing a vector of left values and a vector of
149152
/// right values.
150153
pub fn partition<L, R>(eithers: ~[Either<L, R>]) -> (~[L], ~[R]) {
151-
let mut lefts: ~[L] = ~[];
152-
let mut rights: ~[R] = ~[];
154+
let n_lefts = eithers.iter().count(|elt| elt.is_left());
155+
let mut lefts = vec::with_capacity(n_lefts);
156+
let mut rights = vec::with_capacity(eithers.len() - n_lefts);
153157
for elt in eithers.move_iter() {
154158
match elt {
155159
Left(l) => lefts.push(l),
@@ -182,42 +186,42 @@ mod tests {
182186
#[test]
183187
fn test_lefts() {
184188
let input = ~[Left(10), Right(11), Left(12), Right(13), Left(14)];
185-
let result = lefts(input);
189+
let result = lefts(input.move_iter()).to_owned_vec();
186190
assert_eq!(result, ~[10, 12, 14]);
187191
}
188192

189193
#[test]
190194
fn test_lefts_none() {
191195
let input: ~[Either<int, int>] = ~[Right(10), Right(10)];
192-
let result = lefts(input);
196+
let result = lefts(input.move_iter()).to_owned_vec();
193197
assert_eq!(result.len(), 0u);
194198
}
195199

196200
#[test]
197201
fn test_lefts_empty() {
198202
let input: ~[Either<int, int>] = ~[];
199-
let result = lefts(input);
203+
let result = lefts(input.move_iter()).to_owned_vec();
200204
assert_eq!(result.len(), 0u);
201205
}
202206

203207
#[test]
204208
fn test_rights() {
205209
let input = ~[Left(10), Right(11), Left(12), Right(13), Left(14)];
206-
let result = rights(input);
210+
let result = rights(input.move_iter()).to_owned_vec();
207211
assert_eq!(result, ~[11, 13]);
208212
}
209213

210214
#[test]
211215
fn test_rights_none() {
212216
let input: ~[Either<int, int>] = ~[Left(10), Left(10)];
213-
let result = rights(input);
217+
let result = rights(input.move_iter()).to_owned_vec();
214218
assert_eq!(result.len(), 0u);
215219
}
216220

217221
#[test]
218222
fn test_rights_empty() {
219223
let input: ~[Either<int, int>] = ~[];
220-
let result = rights(input);
224+
let result = rights(input.move_iter()).to_owned_vec();
221225
assert_eq!(result.len(), 0u);
222226
}
223227

src/libstd/result.rs

+84-55
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ use either;
1818
use iterator::Iterator;
1919
use option::{None, Option, Some, OptionIterator};
2020
use vec;
21-
use vec::{OwnedVector, ImmutableVector};
22-
use container::Container;
21+
use vec::OwnedVector;
2322
use to_str::ToStr;
2423
use str::StrSlice;
2524

@@ -269,86 +268,76 @@ pub fn map_opt<T, U: ToStr, V>(o_t: &Option<T>,
269268
}
270269
}
271270

272-
// FIXME: #8228 Replaceable by an external iterator?
273-
/// Maps each element in the vector `ts` using the operation `op`. Should an
274-
/// error occur, no further mappings are performed and the error is returned.
275-
/// Should no error occur, a vector containing the result of each map is
276-
/// returned.
271+
/// Takes each element in the iterator: if it is an error, no further
272+
/// elements are taken, and the error is returned.
273+
/// Should no error occur, a vector containing the values of each Result
274+
/// is returned.
277275
///
278276
/// Here is an example which increments every integer in a vector,
279277
/// checking for overflow:
280278
///
281-
/// fn inc_conditionally(x: uint) -> result<uint,str> {
279+
/// fn inc_conditionally(x: uint) -> Result<uint, &'static str> {
282280
/// if x == uint::max_value { return Err("overflow"); }
283281
/// else { return Ok(x+1u); }
284282
/// }
285-
/// map(~[1u, 2u, 3u], inc_conditionally).chain {|incd|
286-
/// assert!(incd == ~[2u, 3u, 4u]);
287-
/// }
283+
/// let v = [1u, 2, 3];
284+
/// let res = collect(v.iter().map(|&x| inc_conditionally(x)));
285+
/// assert!(res == Ok(~[2u, 3, 4]));
288286
#[inline]
289-
pub fn map_vec<T,U,V>(ts: &[T], op: &fn(&T) -> Result<V,U>)
290-
-> Result<~[V],U> {
291-
let mut vs: ~[V] = vec::with_capacity(ts.len());
292-
for t in ts.iter() {
293-
match op(t) {
294-
Ok(v) => vs.push(v),
295-
Err(u) => return Err(u)
287+
pub fn collect<T, E, Iter: Iterator<Result<T, E>>>(mut iterator: Iter)
288+
-> Result<~[T], E> {
289+
let (lower, _) = iterator.size_hint();
290+
let mut vs: ~[T] = vec::with_capacity(lower);
291+
for t in iterator {
292+
match t {
293+
Ok(v) => vs.push(v),
294+
Err(u) => return Err(u)
296295
}
297296
}
298-
return Ok(vs);
297+
Ok(vs)
299298
}
300299

301-
// FIXME: #8228 Replaceable by an external iterator?
302-
/// Same as map, but it operates over two parallel vectors.
300+
/// Perform a fold operation over the result values from an iterator.
303301
///
304-
/// A precondition is used here to ensure that the vectors are the same
305-
/// length. While we do not often use preconditions in the standard
306-
/// library, a precondition is used here because result::t is generally
307-
/// used in 'careful' code contexts where it is both appropriate and easy
308-
/// to accommodate an error like the vectors being of different lengths.
302+
/// If an `Err` is encountered, it is immediately returned.
303+
/// Otherwise, the folded value is returned.
309304
#[inline]
310-
pub fn map_vec2<S, T, U: ToStr, V>(ss: &[S], ts: &[T],
311-
op: &fn(&S,&T) -> Result<V,U>) -> Result<~[V],U> {
312-
assert!(vec::same_length(ss, ts));
313-
let n = ts.len();
314-
let mut vs = vec::with_capacity(n);
315-
let mut i = 0u;
316-
while i < n {
317-
match op(&ss[i],&ts[i]) {
318-
Ok(v) => vs.push(v),
319-
Err(u) => return Err(u)
305+
pub fn fold<T, V, E,
306+
Iter: Iterator<Result<T, E>>>(
307+
mut iterator: Iter,
308+
mut init: V,
309+
f: &fn(V, T) -> V)
310+
-> Result<V, E> {
311+
for t in iterator {
312+
match t {
313+
Ok(v) => init = f(init, v),
314+
Err(u) => return Err(u)
320315
}
321-
i += 1u;
322316
}
323-
return Ok(vs);
317+
Ok(init)
324318
}
325319

326-
// FIXME: #8228 Replaceable by an external iterator?
327-
/// Applies op to the pairwise elements from `ss` and `ts`, aborting on
328-
/// error. This could be implemented using `map_zip()` but it is more efficient
329-
/// on its own as no result vector is built.
320+
/// Perform a trivial fold operation over the result values
321+
/// from an iterator.
322+
///
323+
/// If an `Err` is encountered, it is immediately returned.
324+
/// Otherwise, a simple `Ok(())` is returned.
330325
#[inline]
331-
pub fn iter_vec2<S, T, U: ToStr>(ss: &[S], ts: &[T],
332-
op: &fn(&S,&T) -> Result<(),U>) -> Result<(),U> {
333-
assert!(vec::same_length(ss, ts));
334-
let n = ts.len();
335-
let mut i = 0u;
336-
while i < n {
337-
match op(&ss[i],&ts[i]) {
338-
Ok(()) => (),
339-
Err(u) => return Err(u)
340-
}
341-
i += 1u;
342-
}
343-
return Ok(());
326+
pub fn fold_<T, E, Iter: Iterator<Result<T, E>>>(
327+
iterator: Iter)
328+
-> Result<(), E> {
329+
fold(iterator, (), |_, _| ())
344330
}
345331

332+
346333
#[cfg(test)]
347334
mod tests {
348335
use super::*;
349336

350337
use either;
338+
use iterator::range;
351339
use str::OwnedStr;
340+
use vec::ImmutableVector;
352341

353342
pub fn op1() -> Result<int, ~str> { Ok(666) }
354343

@@ -431,4 +420,44 @@ mod tests {
431420
assert_eq!(r.to_either(), either::Right(100));
432421
assert_eq!(err.to_either(), either::Left(404));
433422
}
423+
424+
#[test]
425+
fn test_collect() {
426+
assert_eq!(collect(range(0, 0)
427+
.map(|_| Ok::<int, ()>(0))),
428+
Ok(~[]));
429+
assert_eq!(collect(range(0, 3)
430+
.map(|x| Ok::<int, ()>(x))),
431+
Ok(~[0, 1, 2]));
432+
assert_eq!(collect(range(0, 3)
433+
.map(|x| if x > 1 { Err(x) } else { Ok(x) })),
434+
Err(2));
435+
436+
// test that it does not take more elements than it needs
437+
let functions = [|| Ok(()), || Err(1), || fail!()];
438+
439+
assert_eq!(collect(functions.iter().map(|f| (*f)())),
440+
Err(1));
441+
}
442+
443+
#[test]
444+
fn test_fold() {
445+
assert_eq!(fold_(range(0, 0)
446+
.map(|_| Ok::<(), ()>(()))),
447+
Ok(()));
448+
assert_eq!(fold(range(0, 3)
449+
.map(|x| Ok::<int, ()>(x)),
450+
0, |a, b| a + b),
451+
Ok(3));
452+
assert_eq!(fold_(range(0, 3)
453+
.map(|x| if x > 1 { Err(x) } else { Ok(()) })),
454+
Err(2));
455+
456+
// test that it does not take more elements than it needs
457+
let functions = [|| Ok(()), || Err(1), || fail!()];
458+
459+
assert_eq!(fold_(functions.iter()
460+
.map(|f| (*f)())),
461+
Err(1));
462+
}
434463
}

0 commit comments

Comments
 (0)