Skip to content

Commit f10be03

Browse files
committed
Implement DoubleEndedIterator on Range
Range is now invertable as long as its element type conforms to Integer. Remove int::range_rev() et al in favor of range().invert().
1 parent cdba212 commit f10be03

File tree

8 files changed

+62
-71
lines changed

8 files changed

+62
-71
lines changed

src/libextra/smallintmap.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
#[allow(missing_doc)];
1717

1818
use std::iterator::{Iterator, IteratorUtil, Enumerate, FilterMap, Invert};
19-
use std::uint;
2019
use std::util::replace;
2120
use std::vec::{VecIterator, VecMutIterator};
2221
use std::vec;
@@ -150,12 +149,13 @@ impl<V> SmallIntMap<V> {
150149

151150
/// Visit all key-value pairs in reverse order
152151
pub fn each_reverse<'a>(&'a self, it: &fn(uint, &'a V) -> bool) -> bool {
153-
do uint::range_rev(self.v.len(), 0) |i| {
152+
for i in range(0, self.v.len()).invert() {
154153
match self.v[i] {
155-
Some(ref elt) => it(i, elt),
156-
None => true
154+
Some(ref elt) => if !it(i, elt) { return false },
155+
None => ()
157156
}
158157
}
158+
true
159159
}
160160

161161
pub fn get<'a>(&'a self, key: &uint) -> &'a V {

src/libstd/iterator.rs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ implementing the `Iterator` trait.
1818
*/
1919

2020
use cmp;
21-
use num::{Zero, One, Saturating};
21+
use num::{Zero, One, Integer, Saturating};
2222
use option::{Option, Some, None};
23-
use ops::{Add, Mul};
23+
use ops::{Add, Mul, Sub};
2424
use cmp::Ord;
2525
use clone::Clone;
2626
use uint;
@@ -1531,7 +1531,7 @@ pub fn range<A: Add<A, A> + Ord + Clone + One>(start: A, stop: A) -> Range<A> {
15311531
Range{state: start, stop: stop, one: One::one()}
15321532
}
15331533

1534-
impl<A: Add<A, A> + Ord + Clone + One> Iterator<A> for Range<A> {
1534+
impl<A: Add<A, A> + Ord + Clone> Iterator<A> for Range<A> {
15351535
#[inline]
15361536
fn next(&mut self) -> Option<A> {
15371537
if self.state < self.stop {
@@ -1544,6 +1544,22 @@ impl<A: Add<A, A> + Ord + Clone + One> Iterator<A> for Range<A> {
15441544
}
15451545
}
15461546

1547+
impl<A: Sub<A, A> + Integer + Ord + Clone> DoubleEndedIterator<A> for Range<A> {
1548+
#[inline]
1549+
fn next_back(&mut self) -> Option<A> {
1550+
if self.stop > self.state {
1551+
// Integer doesn't technically define this rule, but we're going to assume that every
1552+
// Integer is reachable from every other one by adding or subtracting enough Ones. This
1553+
// seems like a reasonable-enough rule that every Integer should conform to, even if it
1554+
// can't be statically checked.
1555+
self.stop = self.stop - self.one;
1556+
Some(self.stop.clone())
1557+
} else {
1558+
None
1559+
}
1560+
}
1561+
}
1562+
15471563
impl<A: Add<A, A> + Clone> Iterator<A> for Counter<A> {
15481564
#[inline]
15491565
fn next(&mut self) -> Option<A> {
@@ -2121,4 +2137,17 @@ mod tests {
21212137
check_randacc_iter(xs.iter().cycle().take_(27), 27);
21222138
check_randacc_iter(empty.iter().cycle(), 0);
21232139
}
2140+
2141+
#[test]
2142+
fn test_double_ended_range() {
2143+
assert_eq!(range(11i, 14).invert().collect::<~[int]>(), ~[13i, 12, 11]);
2144+
for _ in range(10i, 0).invert() {
2145+
fail!("unreachable");
2146+
}
2147+
2148+
assert_eq!(range(11u, 14).invert().collect::<~[uint]>(), ~[13u, 12, 11]);
2149+
for _ in range(10u, 0).invert() {
2150+
fail!("unreachable");
2151+
}
2152+
}
21242153
}

src/libstd/num/int_macros.rs

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -124,14 +124,6 @@ pub fn range_step_inclusive(start: $T, last: $T, step: $T, it: &fn($T) -> bool)
124124
range_step_core(start, last, step, Closed, it)
125125
}
126126
127-
128-
#[inline]
129-
/// Iterate over the range (`hi`..`lo`]
130-
pub fn range_rev(hi: $T, lo: $T, it: &fn($T) -> bool) -> bool {
131-
if hi == min_value { return true; }
132-
range_step_inclusive(hi-1, lo, -1 as $T, it)
133-
}
134-
135127
impl Num for $T {}
136128
137129
#[cfg(not(test))]
@@ -889,10 +881,6 @@ mod tests {
889881
fn test_ranges() {
890882
let mut l = ~[];
891883
892-
do range_rev(14,11) |i| {
893-
l.push(i);
894-
true
895-
};
896884
do range_step(20,26,2) |i| {
897885
l.push(i);
898886
true
@@ -917,18 +905,14 @@ mod tests {
917905
l.push(i);
918906
true
919907
};
920-
assert_eq!(l, ~[13,12,11,
921-
20,22,24,
908+
assert_eq!(l, ~[20,22,24,
922909
36,34,32,
923910
max_value-2,
924911
max_value-3,max_value-1,
925912
min_value+2,
926913
min_value+3,min_value+1]);
927914
928915
// None of the `fail`s should execute.
929-
do range_rev(0,10) |_i| {
930-
fail!(~"unreachable");
931-
};
932916
do range_step(10,0,1) |_i| {
933917
fail!(~"unreachable");
934918
};

src/libstd/num/uint_macros.rs

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -125,13 +125,6 @@ pub fn range_step_inclusive(start: $T, last: $T, step: $T_SIGNED, it: &fn($T) ->
125125
range_step_core(start, last, step, Closed, it)
126126
}
127127

128-
#[inline]
129-
/// Iterate over the range (`hi`..`lo`]
130-
pub fn range_rev(hi: $T, lo: $T, it: &fn($T) -> bool) -> bool {
131-
if hi == min_value { return true; }
132-
range_step_inclusive(hi-1, lo, -1 as $T_SIGNED, it)
133-
}
134-
135128
impl Num for $T {}
136129

137130
#[cfg(not(test))]
@@ -654,10 +647,6 @@ mod tests {
654647
pub fn test_ranges() {
655648
let mut l = ~[];
656649
657-
do range_rev(14,11) |i| {
658-
l.push(i);
659-
true
660-
};
661650
do range_step(20,26,2) |i| {
662651
l.push(i);
663652
true
@@ -683,18 +672,14 @@ mod tests {
683672
true
684673
};
685674
686-
assert_eq!(l, ~[13,12,11,
687-
20,22,24,
675+
assert_eq!(l, ~[20,22,24,
688676
36,34,32,
689677
max_value-2,
690678
max_value-3,max_value-1,
691679
min_value+2,
692680
min_value+3,min_value+1]);
693681
694682
// None of the `fail`s should execute.
695-
do range_rev(0,0) |_i| {
696-
fail!("unreachable");
697-
};
698683
do range_step(10,0,1) |_i| {
699684
fail!("unreachable");
700685
};

src/libstd/run.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,6 @@ fn spawn_process_os(prog: &str, args: &[~str],
632632

633633
use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp};
634634
use libc::funcs::bsd44::getdtablesize;
635-
use int;
636635

637636
mod rustrt {
638637
use libc::c_void;
@@ -665,10 +664,9 @@ fn spawn_process_os(prog: &str, args: &[~str],
665664
fail!("failure in dup3(err_fd, 2): %s", os::last_os_error());
666665
}
667666
// close all other fds
668-
do int::range_rev(getdtablesize() as int, 3) |fd| {
667+
for fd in range(3, getdtablesize()).invert() {
669668
close(fd as c_int);
670-
true
671-
};
669+
}
672670

673671
do with_dirp(dir) |dirp| {
674672
if !dirp.is_null() && chdir(dirp) == -1 {

src/libstd/trie.rs

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -271,8 +271,8 @@ impl<T> TrieNode<T> {
271271

272272
impl<T> TrieNode<T> {
273273
fn each<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) -> bool {
274-
for idx in range(0u, self.children.len()) {
275-
match self.children[idx] {
274+
for elt in self.children.iter() {
275+
match *elt {
276276
Internal(ref x) => if !x.each(|i,t| f(i,t)) { return false },
277277
External(k, ref v) => if !f(&k, v) { return false },
278278
Nothing => ()
@@ -282,13 +282,14 @@ impl<T> TrieNode<T> {
282282
}
283283

284284
fn each_reverse<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) -> bool {
285-
do uint::range_rev(self.children.len(), 0) |idx| {
286-
match self.children[idx] {
287-
Internal(ref x) => x.each_reverse(|i,t| f(i,t)),
288-
External(k, ref v) => f(&k, v),
289-
Nothing => true
285+
for elt in self.children.rev_iter() {
286+
match *elt {
287+
Internal(ref x) => if !x.each_reverse(|i,t| f(i,t)) { return false },
288+
External(k, ref v) => if !f(&k, v) { return false },
289+
Nothing => ()
290290
}
291291
}
292+
true
292293
}
293294

294295
fn mutate_values<'a>(&'a mut self, f: &fn(&uint, &mut T) -> bool) -> bool {
@@ -539,10 +540,9 @@ mod test_map {
539540
fn test_each_break() {
540541
let mut m = TrieMap::new();
541542

542-
do uint::range_rev(uint::max_value, uint::max_value - 10000) |x| {
543+
for x in range(uint::max_value - 10000, uint::max_value).invert() {
543544
m.insert(x, x / 2);
544-
true
545-
};
545+
}
546546

547547
let mut n = uint::max_value - 10000;
548548
do m.each |k, v| {
@@ -580,10 +580,9 @@ mod test_map {
580580
fn test_each_reverse_break() {
581581
let mut m = TrieMap::new();
582582

583-
do uint::range_rev(uint::max_value, uint::max_value - 10000) |x| {
583+
for x in range(uint::max_value - 10000, uint::max_value).invert() {
584584
m.insert(x, x / 2);
585-
true
586-
};
585+
}
587586

588587
let mut n = uint::max_value - 1;
589588
do m.each_reverse |k, v| {
@@ -634,10 +633,9 @@ mod test_map {
634633
let last = uint::max_value;
635634

636635
let mut map = TrieMap::new();
637-
do uint::range_rev(last, first) |x| {
636+
for x in range(first, last).invert() {
638637
map.insert(x, x / 2);
639-
true
640-
};
638+
}
641639

642640
let mut i = 0;
643641
for (k, &v) in map.iter() {

src/test/bench/core-map.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,24 +53,21 @@ fn descending<M: MutableMap<uint, uint>>(map: &mut M, n_keys: uint) {
5353
io::println(" Descending integers:");
5454

5555
do timed("insert") {
56-
do uint::range_rev(n_keys, 0) |i| {
56+
for i in range(0, n_keys).invert() {
5757
map.insert(i, i + 1);
58-
true
59-
};
58+
}
6059
}
6160

6261
do timed("search") {
63-
do uint::range_rev(n_keys, 0) |i| {
62+
for i in range(0, n_keys).invert() {
6463
assert_eq!(map.find(&i).unwrap(), &(i + 1));
65-
true
66-
};
64+
}
6765
}
6866

6967
do timed("remove") {
70-
do uint::range_rev(n_keys, 0) |i| {
68+
for i in range(0, n_keys) {
7169
assert!(map.remove(&i));
72-
true
73-
};
70+
}
7471
}
7572
}
7673

src/test/run-pass/num-range-rev.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ fn int_range(lo: int, hi: int, it: &fn(int) -> bool) -> bool {
2020
}
2121

2222
fn uint_range_rev(hi: uint, lo: uint, it: &fn(uint) -> bool) -> bool {
23-
uint::range_rev(hi, lo, it)
23+
range(lo, hi).invert().advance(it)
2424
}
2525

2626
fn int_range_rev(hi: int, lo: int, it: &fn(int) -> bool) -> bool {
27-
int::range_rev(hi, lo, it)
27+
range(lo, hi).invert().advance(it)
2828
}
2929

3030
fn int_range_step(a: int, b: int, step: int, it: &fn(int) -> bool) -> bool {

0 commit comments

Comments
 (0)