61b5194f8c92410e1f1ceba578283c7f9d241151
[nit.git] / lib / standard / collection / range.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2004-2008 Jean Privat <jean@pryen.org>
4 #
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
11 # another product.
12
13 # Module for range of discrete objects.
14 module range
15
16 import abstract_collection
17
18 # Range of discrete objects.
19 class Range[E: Discrete]
20 super Collection[E]
21
22 redef var first: E
23
24 # Get the last element.
25 var last: E
26
27 # Get the element after the last one.
28 var after: E
29
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 >= first and item <= last
34
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
38
39 # assert [1..10].count(1) == 1
40 # assert [1..10].count(0) == 0
41 redef fun count(item)
42 do
43 if has(item) then
44 return 1
45 else
46 return 0
47 end
48 end
49
50 redef fun iterator do return new IteratorRange[E](self)
51
52 # assert [1..10].length == 10
53 # assert [1..10[.length == 9
54 # assert [1..1].length == 1
55 # assert [1..-10].length == 0
56 redef fun length
57 do
58 if is_empty then return 0
59 var nb = first.distance(after)
60 if nb > 0 then
61 return nb
62 else
63 return 0
64 end
65 end
66
67 # assert not [1..10[.is_empty
68 # assert not [1..1].is_empty
69 # assert [1..-10].is_empty
70 redef fun is_empty do return first >= after
71
72 # Create a range [`from`, `to`].
73 # The syntax `[from..to]` is equivalent.
74 #
75 # var a = [10..15]
76 # var b = new Range[Int] (10,15)
77 # assert a == b
78 # assert a.to_a == [10, 11, 12, 13, 14, 15]
79 init(from: E, to: E) is old_style_init do
80 first = from
81 last = to
82 after = to.successor(1)
83 end
84
85 # Create a range [`from`, `to`[.
86 # The syntax `[from..to[` is equivalent.
87 #
88 # var a = [10..15[
89 # var b = new Range[Int].without_last(10,15)
90 # assert a == b
91 # assert a.to_a == [10, 11, 12, 13, 14]
92 init without_last(from: E, to: E)
93 do
94 first = from
95 last = to.predecessor(1)
96 after = to
97 end
98
99 # Two ranges are equals if they have the same first and last elements.
100 #
101 # var a = new Range[Int](10, 15)
102 # var b = new Range[Int].without_last(10, 15)
103 # assert a == [10..15]
104 # assert a == [10..16[
105 # assert not a == [10..15[
106 # assert b == [10..15[
107 # assert b == [10..14]
108 # assert not b == [10..15]
109 redef fun ==(o) do
110 return o isa Range[E] and self.first == o.first and self.last == o.last
111 end
112
113 # var a = new Range[Int](10, 15)
114 # assert a.hash == 455
115 # var b = new Range[Int].without_last(10, 15)
116 # assert b.hash == 432
117 redef fun hash do
118 # 11 and 23 are magic numbers empirically determined to be not so bad.
119 return first.hash * 11 + last.hash * 23
120 end
121 end
122
123 private class IteratorRange[E: Discrete]
124 # Iterator on ranges.
125 super Iterator[E]
126 var range: Range[E]
127 redef var item is noinit
128
129 redef fun is_ok do return _item < _range.after
130
131 redef fun next do _item = _item.successor(1)
132
133 init
134 do
135 _item = _range.first
136 end
137 end
138
139 redef class Int
140 # Returns the range from 0 to `self-1`, is used to do:
141 #
142 # var s = new Array[String]
143 # for i in 3.times do s.add "cool"
144 # assert s.join(" ") == "cool cool cool"
145 #
146 # s.clear
147 # for i in 10.times do s.add(i.to_s)
148 # assert s.to_s == "0123456789"
149 fun times: Range[Int] do return [0 .. self[
150 end