1 # $Id: sequence.rb,v 1.7 2011/12/09 09:08:26 machan Exp $
2
3 require 'tmdoc/tmstd/assertion'
4 require 'tmdoc/tmstd/lsm/abstraction'
5
6
7 module TmStd
8
9 module Lsm
10
11 module Collection
12
13 module Sequence
14
15 class Abstract < Collection::Abstract
16 attr_reader :lsm_elements
17 alias to_a lsm_elements
18 alias length size
19
20
21 def initialize(elements = [])
22 Assertion.kind_of elements, Array
23
24 unless Assertion.disable?
25 elem_class = lsm_element_class
26 for element in elements
27 Assertion.kind_of element, elem_class
28 end
29 end
30
31 @lsm_elements = elements
32 end
33
34
35 def dup
36 new_seq = self.class.new @lsm_elements.dup
37
38 Assertion.kind_of new_seq, self.class
39 end
40
41
42 def first
43 Assertion.kind_of @lsm_elements.first, lsm_element_class
44 end
45
46
47 def last
48 Assertion.kind_of @lsm_elements.last, lsm_element_class
49 end
50
51
52 def include?(element)
53 Assertion.kind_of element, lsm_element_class
54
55 result = @lsm_elements.include? element
56
57 Assertion.boolean result
58 end
59
60
61 def to_s(sep = ', ')
62 str = '[' + self.join(sep) + ']'
63
64 Assertion.kind_of str, String
65 end
66
67
68 def join(sep)
69 Assertion.kind_of sep, String
70
71 str = @lsm_elements.map { |element| element.to_s }.join(sep)
72
73 Assertion.kind_of str, String
74 end
75
76
77 def each(&block)
78 @lsm_elements.each(&block)
79
80 nil
81 end
82
83
84 def map_with_index(&block)
85 array = []
86 self.each_with_index do |element, index|
87 array << block.call(element, index)
88 end
89
90 Assertion.kind_of array, Array
91 end
92
93
94 def append(others = [])
95 Assertion.kind_of others, Array
96
97 new_seq = self.class.new(
98 self.to_a + (
99 others.map { |other| other.to_a }
100 ).flatten
101 )
102
103 Assertion.kind_of new_seq, self.class
104 end
105
106
107 # EXAMPLE
108 #
109 # seq = MySequence.new(['A', 'B', 'C'])
110 #
111 # seq + MySequence.new(['X', 'Y', 'Z'])
112 # => ['A', 'B', 'C', 'X', 'Y', 'Z']
113 #
114 # seq
115 # => ['A', 'B', 'C'] (* No Side-effect!! *)
116 #
117 def +(other)
118 Assertion.kind_of other, Sequence::Abstract
119
120 new_seq = self.class.new(@lsm_elements + other.to_a)
121
122 Assertion.kind_of new_seq, self.class
123 end
124
125
126 # EXAMPLE
127 #
128 # seq = MySequence.new(['A', 'B', 'C'])
129 #
130 # seq << 'X'
131 # => ['A', 'B', 'C', 'X']
132 #
133 # seq
134 # => ['A', 'B', 'C'] (* No Side-effect!! *)
135 #
136 def <<(element)
137 Assertion.kind_of element, lsm_element_class
138
139 new_elements = @lsm_elements.dup
140 new_elements.push element
141
142 new_seq = self.class.new new_elements
143
144 Assertion.kind_of new_seq, self.class
145 end
146 alias add <<
147
148 # EXAMPLE
149 #
150 # stack = MyStack.new(['A', 'B'])
151 #
152 # stack.push('C')
153 # => ['A', 'B', 'C']
154 #
155 # stack
156 # => ['A', 'B'] (* No Side-effect!! *)
157 alias push <<
158
159
160 # EXAMPLE
161 #
162 # stack = MyStack.new(['A', 'B', 'C'])
163 #
164 # stack.pop
165 # => [['A', 'B'], 'C']
166 #
167 # poped_stack, poped_elem = stack.pop
168 # => [['A', 'B'], 'C']
169 #
170 # stack
171 # => ['A', 'B', 'C'] (* No Side-effect!! *)
172 def pop
173 pair =
174 case @lsm_elements.size
175 when 0
176 [self.class.new, nil]
177 when 1
178 [self.class.new, @lsm_elements[0]]
179 else
180 [self.class.new(@lsm_elements[0..-2]), @lsm_elements[-1]]
181 end
182
183 # The poped element is a instance of lsm_element_class or nil.
184 Assertion.tuple_of pair, [self.class, Object]
185 end
186
187
188 def __at__(index)
189 Assertion.kind_of index, Integer
190
191 Assertion.assert(0 <= index && index < @lsm_elements.length,
192 "Out of range, index = %d", index
193 )
194
195 Assertion.opt_kind_of @lsm_elements[index], lsm_element_class
196 end
197 end
198
199
200
201 module Mutable
202 def add!(element)
203 Assertion.kind_of element, lsm_element_class
204
205 @lsm_elements.push element
206
207 nil
208 end
209
210
211 def push!(element)
212 Assertion.kind_of element, lsm_element_class
213
214 @lsm_elements.push element
215
216 nil
217 end
218
219
220 def pop!
221 poped_elem = @lsm_elements.pop
222
223 Assertion.kind_of poped_elem, lsm_element_class
224 end
225 end
226
227
228
229 module Equalable
230 def hash
231 Assertion.kind_of self.to_s.hash, Integer
232 end
233
234
235 def ==(other)
236 Assertion.boolean self.eql?(other)
237 end
238
239
240 def eql?(other)
241 unless other.kind_of?(self.class)
242 return false
243 end
244
245 if self.empty? && other.empty?
246 return true
247 end
248
249 if self.length != other.length
250 return false
251 end
252
253 self.each_with_index do |elem, i|
254 if elem != other.__at__(i)
255 return false
256 end
257 end
258
259 true
260 end
261
262
263 def freeze_equality!
264 for element in @lsm_elements
265 case element
266 when String, Integer
267 element.freeze
268 else
269 element.freeze_equality!
270 end
271 end
272 @lsm_elements.freeze
273
274 nil
275 end
276 end
277
278
279
280 module Comparable
281 include ::Comparable
282
283
284 def <=>(other)
285 Assertion.kind_of other, Abstract
286
287 if self.empty? && other.empty?
288 return 0
289 end
290
291 self_len = self.length
292 other_len = other.length
293 min_len = self_len < other_len ? self_len : other_len
294
295 for i in 0..(min_len - 1)
296 result = self.__at__(i) <=> other.__at__(i)
297 if result != 0
298 return result
299 end
300 end
301
302 if self_len == other_len
303 0
304 elsif self_len < other_len
305 -1
306 else
307 1
308 end
309 end
310 end
311
312 end # TmStd::Lsm::Collection::Sequence
313
314 end # TmStd::Lsm::Collection
315
316
317
318 class SeqOfString < Collection::Sequence::Abstract
319 LSM_ELEMENT_CLASS = String
320 end
321
322 end # TmStd::Lsm
323
324 end # TmStd