1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2004-2008 Jean Privat <jean@pryen.org>
5 # This file is free software, which comes along with NIT. This software is
6 # distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
7 # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
8 # PARTICULAR PURPOSE. You can modify it is you want, provided this header
9 # is kept unaltered, and a notification of the changes is added.
10 # You are allowed to redistribute it and sell it, alone or is a part of
13 # Module for range of discrete objects.
16 import abstract_collection
18 # Range of discrete objects.
19 class Range[E
: Discrete]
24 # Get the last element.
27 # Get the element after the last one.
30 # assert [1..10].has(5)
31 # assert [1..10].has(10)
32 # assert not [1..10[.has(10)
33 redef fun has
(item
) do return item
isa Comparable and item
>= first
and item
<= last
35 # assert [1..1].has_only(1)
36 # assert not [1..10].has_only(1)
37 redef fun has_only
(item
) do return first
== item
and item
== last
or is_empty
39 # assert [1..10].count(1) == 1
40 # assert [1..10].count(0) == 0
50 redef fun iterator
do return new IteratorRange[E
](self)
52 # Gets an iterator starting at the end and going backwards
54 # var reviter = [1..4].reverse_iterator
55 # assert reviter.to_a == [4,3,2,1]
57 # reviter = [1..4[.reverse_iterator
58 # assert reviter.to_a == [3,2,1]
59 fun reverse_iterator
: Iterator[E
] do return new ReverseIteratorRange[E
](self)
61 # assert [1..10].length == 10
62 # assert [1..10[.length == 9
63 # assert [1..1].length == 1
64 # assert [1..-10].length == 0
67 if is_empty
then return 0
68 var nb
= first
.distance
(after
)
76 # assert not [1..10[.is_empty
77 # assert not [1..1].is_empty
78 # assert [1..-10].is_empty
79 redef fun is_empty
do return first
>= after
81 # Create a range [`from`, `to`].
82 # The syntax `[from..to]` is equivalent.
85 # var b = new Range[Int] (10,15)
87 # assert a.to_a == [10, 11, 12, 13, 14, 15]
88 init(from
: E
, to
: E
) is old_style_init
do
91 after
= to
.successor
(1)
94 # Create a range [`from`, `to`[.
95 # The syntax `[from..to[` is equivalent.
98 # var b = new Range[Int].without_last(10,15)
100 # assert a.to_a == [10, 11, 12, 13, 14]
101 init without_last
(from
: E
, to
: E
)
105 last
= to
.predecessor
(1)
108 last
= to
.successor
(1)
113 # Two ranges are equals if they have the same first and last elements.
115 # var a = new Range[Int](10, 15)
116 # var b = new Range[Int].without_last(10, 15)
117 # assert a == [10..15]
118 # assert a == [10..16[
119 # assert not a == [10..15[
120 # assert b == [10..15[
121 # assert b == [10..14]
122 # assert not b == [10..15]
124 return o
isa Range[E
] and self.first
== o
.first
and self.last
== o
.last
127 # var a = new Range[Int](10, 15)
128 # assert a.hash == 455
129 # var b = new Range[Int].without_last(10, 15)
130 # assert b.hash == 432
132 # 11 and 23 are magic numbers empirically determined to be not so bad.
133 return first
.hash
* 11 + last
.hash
* 23
136 # Gets an iterator that progress with a given step.
138 # The main usage is in `for` construction.
141 # for i in [10..25].step(10) do assert i == 10 or i == 20
144 # But `step` is usable as any kind of iterator.
147 # assert [10..27].step(5).to_a == [10,15,20,25]
150 # If `step == 1`, then it is equivalent to the default `iterator`.
153 # assert [1..5].step(1).to_a == [1..5].to_a
156 # If `step` is negative, then the iterator will iterate on ranges whose `first` > `last`.
159 # assert [25..12].step(-5).to_a == [25,20,15]
162 # On such ranges, the default `iterator` will be empty
165 # assert [5..1].step(1).to_a.is_empty
166 # assert [5..1].iterator.to_a.is_empty
167 # assert [5..1].to_a.is_empty
168 # assert [5..1].is_empty
171 # Note that on non-empty range, iterating with a negative step will be empty
174 # assert [1..5].step(-1).to_a.is_empty
176 fun step
(step
: Int): Iterator[E
]
182 i
= new DowntoIteratorRange[E
](self)
186 if step
== 1 then return i
187 return i
.to_step
(step
)
191 # Iterator on ranges.
192 private class IteratorRange[E
: Discrete]
195 redef var item
is noinit
197 redef fun is_ok
do return _item
< _range
.after
199 redef fun next
do _item
= _item
.successor
(1)
207 # Reverse iterator on ranges.
208 private class ReverseIteratorRange[E
: Discrete]
211 redef var item
is noinit
213 redef fun is_ok
do return _item
>= _range
.first
215 redef fun next
do _item
= _item
.predecessor
(1)
223 # Iterator on ranges.
224 private class DowntoIteratorRange[E
: Discrete]
225 super IndexedIterator[E
]
227 redef var item
is noinit
228 redef fun index
do return _item
.distance
(_range
.first
)
230 redef fun is_ok
do return _item
>= _range
.last
232 redef fun next
do _item
= _item
.predecessor
(1)
241 # Returns the range from 0 to `self-1`.
243 # assert 3.times == [0..3[
244 # assert 10.times == [0..10[
245 # assert ((-1).times).is_empty
247 # This can be usefull for loops:
249 # var s = new Array[String]
250 # for i in 3.times do s.add "cool"
251 # assert s.join(" ") == "cool cool cool"
252 fun times
: Range[Int] do return [0 .. self[