random-accessible 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.en +31 -0
- data/lib/#random-readable.rb# +598 -0
- data/lib/common-traits.rb +71 -0
- data/lib/random-accessible.rb +340 -0
- data/lib/random-readable.rb +598 -0
- data/lib/random-writable.rb +302 -0
- data/test/test-suite.rb +3 -0
- metadata +74 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
# Author:: Natsuki Kawai (natsuki.kawai@gmail.com)
|
2
|
+
# Copyright:: Copyright 2011 Natsuki Kawai
|
3
|
+
# License:: 2-clause BSDL or Ruby's
|
4
|
+
|
5
|
+
|
6
|
+
module RandomAccessible
|
7
|
+
|
8
|
+
# RandomAccessible::CommonTraits mixin provides methods
|
9
|
+
# commonly used for read and write access.
|
10
|
+
module CommonTraits
|
11
|
+
|
12
|
+
# Same as Array's.
|
13
|
+
# This method evaluates no element of the class.
|
14
|
+
# This method raises NotImplementedError
|
15
|
+
# if the class provides neither size nor length method.
|
16
|
+
def each_index(&block)
|
17
|
+
if block.nil?
|
18
|
+
Enumerator.new do |y|
|
19
|
+
size.times do |i|
|
20
|
+
y << i
|
21
|
+
end
|
22
|
+
end
|
23
|
+
else
|
24
|
+
size.times do |i|
|
25
|
+
block.call(i)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Same as Array's.
|
31
|
+
# This method evaluates no element of the class.
|
32
|
+
# This method raises NotImplementedError
|
33
|
+
# if the class provides neither size nor length method.
|
34
|
+
def empty?
|
35
|
+
if has_size?
|
36
|
+
size <= 0
|
37
|
+
else
|
38
|
+
false
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns true if the object implements size or length method.
|
43
|
+
def has_size?
|
44
|
+
return method(:size).owner != CommonTraits ||
|
45
|
+
method(:length).owner != CommonTraits
|
46
|
+
end
|
47
|
+
private :has_size?
|
48
|
+
|
49
|
+
# This method is a size-provider (see README).
|
50
|
+
# Overriding method returns the number of the elements.
|
51
|
+
def size
|
52
|
+
if method(:length).owner == CommonTraits
|
53
|
+
raise NotImplementedError,
|
54
|
+
"#{self.class.to_s} overrides neither length method nor size method."
|
55
|
+
end
|
56
|
+
return length
|
57
|
+
end
|
58
|
+
|
59
|
+
# This method is a size-provider (see README).
|
60
|
+
# Overriding method returns the number of the elements.
|
61
|
+
def length
|
62
|
+
if method(:size).owner == CommonTraits
|
63
|
+
raise NotImplementedError,
|
64
|
+
"#{self.class.to_s} overrides neither length method nor size method."
|
65
|
+
end
|
66
|
+
return size
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,340 @@
|
|
1
|
+
# Author:: Natsuki Kawai (natsuki.kawai@gmail.com)
|
2
|
+
# Copyright:: Copyright 2011 Natsuki Kawai
|
3
|
+
# License:: 2-clause BSDL or Ruby's
|
4
|
+
|
5
|
+
|
6
|
+
require 'random-readable'
|
7
|
+
require 'random-writable'
|
8
|
+
|
9
|
+
# RandomAccessible mixin provides all instance methods of Array.
|
10
|
+
# Some methods are defined in RandomReadable or RandomWritable.
|
11
|
+
# The class must provide one or more methods from read-accessor group ([], at, read_access).
|
12
|
+
# The class must provide one or more methods from replace-accessor
|
13
|
+
# ([]=, replace_at, replace_access) and shrink-accessor (shrink) respectively.
|
14
|
+
# The class may provide insert-accessor (insert_access, insert_at, insert)
|
15
|
+
# and delete-accessor (delete_access, delete_at).
|
16
|
+
# The class may provide one size-provider (size, length).
|
17
|
+
# See the docment of RandomReadable and RandomWritable.
|
18
|
+
module RandomAccessible
|
19
|
+
|
20
|
+
include RandomReadable
|
21
|
+
include RandomWritable
|
22
|
+
|
23
|
+
# TODO: Override RandomWritable.#[]= for optimization.
|
24
|
+
|
25
|
+
# Define modifiers.
|
26
|
+
def self.define_modifying_method(*methods)
|
27
|
+
methods.each do |method|
|
28
|
+
modifier = method.to_s + '!'
|
29
|
+
define_method modifier do |*args, &block|
|
30
|
+
res = send(method, *args, &block)
|
31
|
+
if self == res
|
32
|
+
return nil
|
33
|
+
else
|
34
|
+
replace(res)
|
35
|
+
return self
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
private_class_method :define_modifying_method
|
41
|
+
|
42
|
+
# TODO: Optimize these methods if it is possible.
|
43
|
+
define_modifying_method :compact, :flatten, :uniq
|
44
|
+
|
45
|
+
# Fixed-number-argument version of insert(pos, *val).
|
46
|
+
# This method works without override of insert_access.
|
47
|
+
def insert_at(pos, val)
|
48
|
+
expand 1
|
49
|
+
(pos...(size - 1)).reverse_each do |i|
|
50
|
+
self[i + 1] = self[i]
|
51
|
+
end
|
52
|
+
self[pos] = val
|
53
|
+
end
|
54
|
+
|
55
|
+
# Same as Array's.
|
56
|
+
# See the docment of RandomReadable#collect.
|
57
|
+
def collect!(&block)
|
58
|
+
if block.nil?
|
59
|
+
Enumerator.new do |y|
|
60
|
+
size.times do |i|
|
61
|
+
self[i] = y.yield(at(i))
|
62
|
+
end
|
63
|
+
end
|
64
|
+
else
|
65
|
+
replace(collect(&block))
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Same as Array's.
|
70
|
+
# See the docment of RandomReadable#collect.
|
71
|
+
alias :map! :collect!
|
72
|
+
|
73
|
+
|
74
|
+
# Same as Array's.
|
75
|
+
# This method raises NotImplementedError
|
76
|
+
# if the class provides no size-provider.
|
77
|
+
def delete(val, &block)
|
78
|
+
deleted = 0
|
79
|
+
if method(:delete_at).owner == RandomAccessible
|
80
|
+
size.times do |i|
|
81
|
+
if at(i) == val
|
82
|
+
deleted += 1
|
83
|
+
else
|
84
|
+
replace_at(i - deleted, at(i))
|
85
|
+
end
|
86
|
+
end
|
87
|
+
shrink deleted
|
88
|
+
else
|
89
|
+
size.times do |i|
|
90
|
+
if at(i) == val
|
91
|
+
delete_at(i - deleted)
|
92
|
+
deleted += 1
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
if deleted > 0
|
98
|
+
return val
|
99
|
+
elsif block.nil?
|
100
|
+
return nil
|
101
|
+
else
|
102
|
+
return block.call
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Same as Array's.
|
107
|
+
# This method raises NotImplementedError
|
108
|
+
# if the class provides no size-provider and pos is negative.
|
109
|
+
# This method works without delete_access.
|
110
|
+
def delete_at(pos)
|
111
|
+
if pos < 0
|
112
|
+
pos += size
|
113
|
+
end
|
114
|
+
if pos < 0 || (has_size? && size <= pos)
|
115
|
+
return nil
|
116
|
+
end
|
117
|
+
|
118
|
+
res = self[pos]
|
119
|
+
((pos + 1)...size).each do |i|
|
120
|
+
replace_at(i - 1, at(i))
|
121
|
+
end
|
122
|
+
shrink 1
|
123
|
+
return res
|
124
|
+
end
|
125
|
+
|
126
|
+
# Same as Array's.
|
127
|
+
# This method raises NotImplementedError
|
128
|
+
# if the class provides no size-provider.
|
129
|
+
def delete_if(&block)
|
130
|
+
if block.nil?
|
131
|
+
reject!
|
132
|
+
else
|
133
|
+
reject!(&block)
|
134
|
+
return self
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# Same as Array's.
|
139
|
+
# This method raises NotImplementedError
|
140
|
+
# if the class provides no size-provider.
|
141
|
+
def reject!(&block)
|
142
|
+
if block.nil?
|
143
|
+
return Enumerator.new do |y|
|
144
|
+
deleted = 0
|
145
|
+
size.times do |i|
|
146
|
+
val = self[i - deleted]
|
147
|
+
if y.yield(val)
|
148
|
+
delete_at(i - deleted)
|
149
|
+
deleted += 1
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
else
|
154
|
+
deleted = 0
|
155
|
+
size.times do |i|
|
156
|
+
val = self[i]
|
157
|
+
if block.call(val)
|
158
|
+
deleted += 1
|
159
|
+
else
|
160
|
+
self[i - deleted] = val
|
161
|
+
end
|
162
|
+
end
|
163
|
+
if deleted > 0
|
164
|
+
shrink deleted
|
165
|
+
return self
|
166
|
+
else
|
167
|
+
return nil
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# Same as Array's.
|
173
|
+
# This method raises NotImplementedError
|
174
|
+
# if the class provides no size-provider.
|
175
|
+
def keep_if(&block)
|
176
|
+
if block.nil?
|
177
|
+
e = reject!
|
178
|
+
return Enumerator.new do |y|
|
179
|
+
i = 0
|
180
|
+
e.each do
|
181
|
+
res = !y.yield(self[i])
|
182
|
+
i += 1 unless res
|
183
|
+
res
|
184
|
+
end
|
185
|
+
end
|
186
|
+
else
|
187
|
+
reject! do |el|
|
188
|
+
!block.call(el)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
# Same as Array's.
|
194
|
+
# This method raises NotImplementedError
|
195
|
+
# if the class provides no size-provider.
|
196
|
+
def pop(*args)
|
197
|
+
# Needs size.
|
198
|
+
if args.size > 1
|
199
|
+
raise ArgumentError, "wrong number of arguments (#{args.size} for 0..1)"
|
200
|
+
end
|
201
|
+
|
202
|
+
res = nil
|
203
|
+
if args.size == 0
|
204
|
+
unless empty?
|
205
|
+
res = at(size - 1)
|
206
|
+
super
|
207
|
+
end
|
208
|
+
else
|
209
|
+
n = args[0]
|
210
|
+
n = size if n > size
|
211
|
+
res = self[(size - n)...size]
|
212
|
+
super n
|
213
|
+
end
|
214
|
+
return res
|
215
|
+
end
|
216
|
+
|
217
|
+
# Same as Array's.
|
218
|
+
# This method raises NotImplementedError
|
219
|
+
# if the class provides no size-provider.
|
220
|
+
def reverse!
|
221
|
+
# TODO: Optimize me.
|
222
|
+
replace(reverse)
|
223
|
+
end
|
224
|
+
|
225
|
+
# Same as Array's.
|
226
|
+
# This method raises NotImplementedError
|
227
|
+
# if the class provides no size-provider.
|
228
|
+
def rotate!(cnt = 1)
|
229
|
+
# TODO: Optimize me.
|
230
|
+
replace(rotate(cnt))
|
231
|
+
end
|
232
|
+
|
233
|
+
alias :select! :keep_if
|
234
|
+
|
235
|
+
# Same as Array's.
|
236
|
+
# This method raises NotImplementedError
|
237
|
+
# if the class provides no size-provider.
|
238
|
+
def shift(*args)
|
239
|
+
if args.size > 1
|
240
|
+
raise ArgumentError, "wrong number of arguments (#{args.size} for 0..1)"
|
241
|
+
end
|
242
|
+
|
243
|
+
if args.empty?
|
244
|
+
res = self[0]
|
245
|
+
super
|
246
|
+
return res
|
247
|
+
else
|
248
|
+
n = args[0]
|
249
|
+
res = self[0...n]
|
250
|
+
super n
|
251
|
+
return res
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
# Same as Array's.
|
256
|
+
# This method raises NotImplementedError
|
257
|
+
# if the class provides no size-provider.
|
258
|
+
def shuffle!
|
259
|
+
# TODO: Optimize me.
|
260
|
+
replace(shuffle)
|
261
|
+
end
|
262
|
+
|
263
|
+
# Same as Array's.
|
264
|
+
# This method raises NotImplementedError
|
265
|
+
# if the class provides neither size-provider nor delete-accessor.
|
266
|
+
def slice!(*args)
|
267
|
+
unless (1..2).include?(args.size)
|
268
|
+
raise ArgumentError, "wrong number of arguments (#{args.size} for 1..2)"
|
269
|
+
end
|
270
|
+
|
271
|
+
if args.size == 2 || args[0].is_a?(Range)
|
272
|
+
start = len = nil
|
273
|
+
if args.size == 2
|
274
|
+
start = args[0]
|
275
|
+
len = args[1]
|
276
|
+
else
|
277
|
+
range = args[0]
|
278
|
+
start = range.first
|
279
|
+
len = range.last - start
|
280
|
+
len += 1 unless range.exclude_end?
|
281
|
+
end
|
282
|
+
res = self[*args]
|
283
|
+
len.times do
|
284
|
+
delete_at(start)
|
285
|
+
end
|
286
|
+
return res
|
287
|
+
else
|
288
|
+
pos = args[0].to_int
|
289
|
+
if pos < 0
|
290
|
+
pos += size
|
291
|
+
end
|
292
|
+
if pos < 0 || size <= pos
|
293
|
+
return nil
|
294
|
+
else
|
295
|
+
res = self[pos]
|
296
|
+
delete_at(pos)
|
297
|
+
return res
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
# Same as Array's.
|
303
|
+
# This method raises NotImplementedError
|
304
|
+
# if the class provides no size-provider.
|
305
|
+
def sort!(&block)
|
306
|
+
# TODO: Optimize me.
|
307
|
+
replace(sort(&block))
|
308
|
+
end
|
309
|
+
|
310
|
+
# Same as Array's.
|
311
|
+
# This method raises NotImplementedError
|
312
|
+
# if the class provides no size-provider.
|
313
|
+
def sort_by!(&block)
|
314
|
+
# TODO: Optimize me.
|
315
|
+
if block.nil?
|
316
|
+
data = []
|
317
|
+
Enumerator.new do |y|
|
318
|
+
each do |el|
|
319
|
+
data << y.yield(el)
|
320
|
+
end
|
321
|
+
i = -1
|
322
|
+
sort_by! do
|
323
|
+
i += 1
|
324
|
+
data[i]
|
325
|
+
end
|
326
|
+
end
|
327
|
+
else
|
328
|
+
replace(sort_by(&block))
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
# Same as Array's.
|
333
|
+
# This method raises NotImplementedError
|
334
|
+
# if the class provides neither size-provider nor insert-accessor.
|
335
|
+
def unshift(*obj)
|
336
|
+
# TODO: Optimize me.
|
337
|
+
insert(0, *obj)
|
338
|
+
end
|
339
|
+
|
340
|
+
end
|
@@ -0,0 +1,598 @@
|
|
1
|
+
# Author:: Natsuki Kawai (natsuki.kawai@gmail.com)
|
2
|
+
# Copyright:: Copyright 2011 Natsuki Kawai
|
3
|
+
# License:: 2-clause BSDL or Ruby's
|
4
|
+
|
5
|
+
|
6
|
+
require 'common-traits'
|
7
|
+
|
8
|
+
# RandomReadable mixin provides non-destructive methods of Array.
|
9
|
+
# The class must provide one or more methods from read-accessor group ([], at, read_access).
|
10
|
+
# The class may provide one size-provider (size, length).
|
11
|
+
# read_access(pos) is similar to "at" method, but the module guarantees the argument is positive.
|
12
|
+
# And if the class provides size or length methods, the argument is less than size or length.
|
13
|
+
# If the class does not provide size-provider, some of the methods of the module
|
14
|
+
# raises NotImplementedError. Please see the document of each method.
|
15
|
+
module RandomReadable
|
16
|
+
|
17
|
+
include RandomAccessible::CommonTraits
|
18
|
+
include Enumerable
|
19
|
+
|
20
|
+
# Returns all elements of the class as an Array.
|
21
|
+
# This method evaluates all elements of the class.
|
22
|
+
# This method raises NotImplementedError
|
23
|
+
# if the class provides neither size nor length method.
|
24
|
+
def to_ary
|
25
|
+
Enumerator.new do |y|
|
26
|
+
size.times do |i|
|
27
|
+
y << at(i)
|
28
|
+
end
|
29
|
+
end.to_a
|
30
|
+
end
|
31
|
+
|
32
|
+
alias :to_a :to_ary
|
33
|
+
|
34
|
+
def delegate_to_array(name, *args, &block)
|
35
|
+
to_ary.send(name, *args, &block)
|
36
|
+
end
|
37
|
+
private :delegate_to_array
|
38
|
+
|
39
|
+
# Same as Array's.
|
40
|
+
# This method evaluates all elements of the class.
|
41
|
+
# This method raises NotImplementedError
|
42
|
+
# if the class provides neither size nor length method.
|
43
|
+
def &(other)
|
44
|
+
delegate_to_array(:&, other)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Same as Array's.
|
48
|
+
# This method evaluates all elements of the class.
|
49
|
+
# This method raises NotImplementedError
|
50
|
+
# if the class provides neither size nor length method.
|
51
|
+
def *(arg)
|
52
|
+
delegate_to_array(:*, arg)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Same as Array's.
|
56
|
+
# This method evaluates all elements of the class.
|
57
|
+
# This method raises NotImplementedError
|
58
|
+
# if the class provides neither size nor length method.
|
59
|
+
def +(other)
|
60
|
+
delegate_to_array(:+, other)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Same as Array's.
|
64
|
+
# This method evaluates all elements of the class.
|
65
|
+
# This method raises NotImplementedError
|
66
|
+
# if the class provides neither size nor length method.
|
67
|
+
def -(other)
|
68
|
+
delegate_to_array(:-, other)
|
69
|
+
end
|
70
|
+
|
71
|
+
# Same as Array's.
|
72
|
+
# This method evaluates elements needed to get results.
|
73
|
+
# This method raises NotImplementedError
|
74
|
+
# if the class provides neither size nor length method.
|
75
|
+
def <=>(other)
|
76
|
+
min_size = [size, other.size].min
|
77
|
+
min_size.times do |i|
|
78
|
+
res = self[i] <=> other[i]
|
79
|
+
return res if res != 0
|
80
|
+
end
|
81
|
+
return size <=> other.size
|
82
|
+
end
|
83
|
+
|
84
|
+
# Same as Array's if the class provides size method.
|
85
|
+
# Same as Object's if not.
|
86
|
+
# This method evaluates elements needed to get results.
|
87
|
+
def ==(other)
|
88
|
+
return super unless has_size?
|
89
|
+
return false if size != other.size
|
90
|
+
size.times do |i|
|
91
|
+
return false if self[i] != other[i]
|
92
|
+
end
|
93
|
+
|
94
|
+
return true
|
95
|
+
end
|
96
|
+
|
97
|
+
# This method is a read-accessor (see README).
|
98
|
+
# If you overrides this method, provide same function as Array's.
|
99
|
+
# Same as Array's.
|
100
|
+
# If the argument is one Integer, this method evaluates one element.
|
101
|
+
# If the argument is a Range or start/length, this method evaluates
|
102
|
+
# elements in the Range or start/length.
|
103
|
+
# This method raises NotImplementedError
|
104
|
+
# if the class provides neither size nor length method, and the argument is minus.
|
105
|
+
def [](*args)
|
106
|
+
if args.size >= 3 || args.size == 0
|
107
|
+
raise ArgumentError, "wrong number of arguments (#{args.size} for 1..2)"
|
108
|
+
end
|
109
|
+
|
110
|
+
if args.size == 2
|
111
|
+
start = args[0].to_int
|
112
|
+
len = args[1].to_int
|
113
|
+
if has_size?
|
114
|
+
return nil if start < -size || size < start
|
115
|
+
return nil if len < 0
|
116
|
+
return Enumerator.new do |y|
|
117
|
+
len.times do |i|
|
118
|
+
y << at(start + i) if start + i < size
|
119
|
+
end
|
120
|
+
end.to_a
|
121
|
+
else
|
122
|
+
return Enumerator.new do |y|
|
123
|
+
len.times do |i|
|
124
|
+
y << at(start + i)
|
125
|
+
end
|
126
|
+
end.to_a
|
127
|
+
end
|
128
|
+
elsif args[0].is_a? Range
|
129
|
+
range = args[0]
|
130
|
+
first = range.first
|
131
|
+
last = range.last
|
132
|
+
|
133
|
+
if has_size?
|
134
|
+
first += size if first < 0
|
135
|
+
last += size if last < 0
|
136
|
+
last -= 1 if range.exclude_end?
|
137
|
+
if first == size || (first == 0 && last < 0)
|
138
|
+
return []
|
139
|
+
elsif first < 0 || size < first
|
140
|
+
return nil
|
141
|
+
end
|
142
|
+
return Enumerator.new do |y|
|
143
|
+
(first..last).each do |i|
|
144
|
+
y << at(i) if 0 <= i && i < size
|
145
|
+
end
|
146
|
+
end.to_a
|
147
|
+
else
|
148
|
+
range.map do |i|
|
149
|
+
at(i)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
else
|
153
|
+
at(args[0])
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# Same as Array's.
|
158
|
+
# This method sequentially evaluates the elements.
|
159
|
+
# Note that this method loops infinitely
|
160
|
+
# if the class provides neither size nor lenght method.
|
161
|
+
def assoc(key)
|
162
|
+
enum = has_size? ? :each : :cycle
|
163
|
+
send(enum) do |el|
|
164
|
+
if el.respond_to?(:[]) && !el.empty? && el[0] == key
|
165
|
+
return el
|
166
|
+
end
|
167
|
+
end
|
168
|
+
return nil
|
169
|
+
end
|
170
|
+
|
171
|
+
# This method is a read-accessor (see README).
|
172
|
+
# If you overrides this method, provide same function as Array's.
|
173
|
+
# Same as Array's.
|
174
|
+
# This method evaluates one element.
|
175
|
+
# even if the argument is minus or out-of-range.
|
176
|
+
def at(pos)
|
177
|
+
pos = pos.to_int
|
178
|
+
|
179
|
+
if 0 <= pos && !has_size?
|
180
|
+
return read_access(pos)
|
181
|
+
elsif 0 <= pos && pos < size
|
182
|
+
return read_access(pos)
|
183
|
+
elsif -size <= pos && pos < 0
|
184
|
+
return read_access(size + pos)
|
185
|
+
else
|
186
|
+
return nil
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
# Need not to override Object#clone and Object#dup
|
191
|
+
|
192
|
+
# Same as Array's.
|
193
|
+
# This method evaluates all elements of the class.
|
194
|
+
# This method raises NotImplementedError
|
195
|
+
# if the class provides neither size nor length method.
|
196
|
+
def combination(n, &block)
|
197
|
+
delegate_to_array(:combination, n, &block)
|
198
|
+
end
|
199
|
+
|
200
|
+
# Same as Array's.
|
201
|
+
# This method evaluates all elements of the class.
|
202
|
+
# This method raises NotImplementedError
|
203
|
+
# if the class provides neither size nor length method.
|
204
|
+
def compact
|
205
|
+
Enumerator.new do |y|
|
206
|
+
each do |el|
|
207
|
+
y << el unless el.nil?
|
208
|
+
end
|
209
|
+
end.to_a
|
210
|
+
end
|
211
|
+
|
212
|
+
# Same as Array's.
|
213
|
+
# This method sequentially evaluates the elements of the class.
|
214
|
+
def cycle
|
215
|
+
if has_size?
|
216
|
+
super
|
217
|
+
else
|
218
|
+
i = 0
|
219
|
+
loop do
|
220
|
+
yield at(i)
|
221
|
+
i += 1
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
# Same as Array's.
|
227
|
+
# This method sequentially evaluates the elements of the class.
|
228
|
+
# This method or the Enumerator raises NotImplementedError
|
229
|
+
# if the class provides neither size nor length method.
|
230
|
+
def each(&block)
|
231
|
+
if block.nil?
|
232
|
+
return Enumerator.new do |y|
|
233
|
+
size.times do |i|
|
234
|
+
y << self[i]
|
235
|
+
end
|
236
|
+
end
|
237
|
+
else
|
238
|
+
size.times do |i|
|
239
|
+
block.call(self[i])
|
240
|
+
end
|
241
|
+
return self
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
# if the object provides size or length, this method is same as Array's
|
246
|
+
# and evaluates minimum elements needed to get results.
|
247
|
+
# If not, this method is same as Object's and evaluates no element.
|
248
|
+
def eql?(other)
|
249
|
+
return false unless self.class.eql?(other.class)
|
250
|
+
return super(other) unless has_size?
|
251
|
+
|
252
|
+
each_index do |i|
|
253
|
+
return false unless at(i).eql?(other.at(i))
|
254
|
+
end
|
255
|
+
return true
|
256
|
+
end
|
257
|
+
|
258
|
+
# Same as Array's.
|
259
|
+
# If the argument is an index, this method evaluates one element.
|
260
|
+
# If the argument is start/length, this method evaluates
|
261
|
+
# elements between the start/length.
|
262
|
+
# This method does not accept a minus index
|
263
|
+
# if the class provides neither size nor length method.
|
264
|
+
def fetch(nth, *args, &block)
|
265
|
+
if args.size >= 2
|
266
|
+
raise ArgumentError, "wrong number of arguments (#{args.size + 1} for 1..2)"
|
267
|
+
end
|
268
|
+
|
269
|
+
if has_size? && (nth < -size || size <= nth)
|
270
|
+
if block != nil
|
271
|
+
# TODO: Warn if ifnone value is present.
|
272
|
+
return block.call
|
273
|
+
elsif args.size == 1
|
274
|
+
return args[0]
|
275
|
+
else
|
276
|
+
raise IndexError,
|
277
|
+
"index #{nth} outsize of the random readable object " \
|
278
|
+
"bounds: #{-size}...#{size}"
|
279
|
+
end
|
280
|
+
else
|
281
|
+
return at(nth)
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
# Same as Array's.
|
286
|
+
# If the argument is an index, this method evaluates one element.
|
287
|
+
# If the argument is start/length, this method evaluates
|
288
|
+
# elements between the start/length.
|
289
|
+
def first(*args)
|
290
|
+
if args.size >= 2
|
291
|
+
raise ArgumentError, "wrong number of arguments (#{args.size + 1} for 1..2)"
|
292
|
+
end
|
293
|
+
|
294
|
+
if args.size == 1
|
295
|
+
width = args[0]
|
296
|
+
width = [width, size].min if has_size?
|
297
|
+
|
298
|
+
return self[0...width]
|
299
|
+
else
|
300
|
+
return at(0)
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
# Same as Array's.
|
305
|
+
# This method evaluates all elements of the class.
|
306
|
+
# This method raises NotImplementedError
|
307
|
+
# if the class provides neither size nor length method.
|
308
|
+
def flatten(lv = nil)
|
309
|
+
delegate_to_array(:flatten, lv)
|
310
|
+
end
|
311
|
+
|
312
|
+
# Same as Array's and evaluates all elements of the class
|
313
|
+
# if the class provides size or length method.
|
314
|
+
# Same as Object's if not.
|
315
|
+
def hash
|
316
|
+
return super unless has_size?
|
317
|
+
|
318
|
+
res = 0
|
319
|
+
each do |el|
|
320
|
+
res += el.hash
|
321
|
+
end
|
322
|
+
return res
|
323
|
+
end
|
324
|
+
|
325
|
+
def include?(val = nil, &block)
|
326
|
+
!!index(val, &block)
|
327
|
+
end
|
328
|
+
|
329
|
+
# Same as Array's.
|
330
|
+
# This method evaluates the elements sequentially.
|
331
|
+
# This method raises NotImplementedError
|
332
|
+
# if the class provides neither size nor length method.
|
333
|
+
def index(val = nil, &block)
|
334
|
+
# needs size
|
335
|
+
if block.nil?
|
336
|
+
each_with_index do |el, index|
|
337
|
+
return index if el == val
|
338
|
+
end
|
339
|
+
else
|
340
|
+
each_with_index do |el, index|
|
341
|
+
return index if block.call(el)
|
342
|
+
end
|
343
|
+
end
|
344
|
+
return nil
|
345
|
+
end
|
346
|
+
|
347
|
+
# indexes is not defined on Ruby 1.9.
|
348
|
+
|
349
|
+
# Same as Array's and evaluates all elements of the class
|
350
|
+
# if the class provides size or length method.
|
351
|
+
# Same as Object's if not.
|
352
|
+
def to_s
|
353
|
+
return super unless has_size?
|
354
|
+
|
355
|
+
to_ary.to_s
|
356
|
+
end
|
357
|
+
|
358
|
+
# Same as Array's and evaluates all elements of the class
|
359
|
+
# if the class provides size or length method.
|
360
|
+
# Same as Object's if not.
|
361
|
+
def inspect
|
362
|
+
return super unless has_size?
|
363
|
+
|
364
|
+
to_ary.inspect
|
365
|
+
end
|
366
|
+
|
367
|
+
# Same as Array's.
|
368
|
+
# This method evaluates all elements of the class.
|
369
|
+
# This method raises NotImplementedError
|
370
|
+
# if the class provides neither size nor length method.
|
371
|
+
def join(sep = $,)
|
372
|
+
to_ary.join(sep)
|
373
|
+
end
|
374
|
+
|
375
|
+
# Same as Array's.
|
376
|
+
# This method evaluates minimum elements of the class.
|
377
|
+
# This method raises NotImplementedError
|
378
|
+
# if the class provides neither size nor length method.
|
379
|
+
def last(n = nil)
|
380
|
+
if n.nil?
|
381
|
+
at(size - 1)
|
382
|
+
else
|
383
|
+
n = size if n > size
|
384
|
+
Enumerator.new do |y|
|
385
|
+
n.times do |i|
|
386
|
+
y << at(size - n + i)
|
387
|
+
end
|
388
|
+
end.to_a
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
# Same as Array's.
|
393
|
+
# This method evaluates all elements of the class.
|
394
|
+
# (TODO: Stop evaluating unnecessary elelments)
|
395
|
+
# This method raises NotImplementedError
|
396
|
+
# if the class provides neither size nor length method.
|
397
|
+
def pack(template)
|
398
|
+
delegate_to_array(:pack, template)
|
399
|
+
end
|
400
|
+
|
401
|
+
# Same as Array's.
|
402
|
+
# This method evaluates all elements of the class.
|
403
|
+
# This method raises NotImplementedError
|
404
|
+
# if the class provides neither size nor length method.
|
405
|
+
def permutation(n, &block)
|
406
|
+
delegate_to_array(:permutation, n, &block)
|
407
|
+
end
|
408
|
+
|
409
|
+
# Same as Array's.
|
410
|
+
# This method evaluates all elements of the class.
|
411
|
+
# This method raises NotImplementedError
|
412
|
+
# if the class provides neither size nor length method.
|
413
|
+
def product(*lists, &block)
|
414
|
+
delegate_to_array(:product, *lists, &block)
|
415
|
+
end
|
416
|
+
|
417
|
+
# Same as Array's.
|
418
|
+
# This method evaluates minimum elements of the class.
|
419
|
+
# This method raises NotImplementedError
|
420
|
+
# if the class provides neither size nor length method.
|
421
|
+
def rassoc(obj)
|
422
|
+
each do |el|
|
423
|
+
if el.respond_to?(:[]) && el.size >= 2 && el[1] == obj
|
424
|
+
return el
|
425
|
+
end
|
426
|
+
end
|
427
|
+
return nil
|
428
|
+
end
|
429
|
+
|
430
|
+
# Same as Array's.
|
431
|
+
# This method evaluates all elements of the class.
|
432
|
+
# This method raises NotImplementedError
|
433
|
+
# if the class provides neither size nor length method.
|
434
|
+
def repeated_combination(n, &block)
|
435
|
+
delegate_to_array(:repeated_combination, n, &block)
|
436
|
+
end
|
437
|
+
|
438
|
+
# Same as Array's.
|
439
|
+
# This method evaluates all elements of the class.
|
440
|
+
# This method raises NotImplementedError
|
441
|
+
# if the class provides neither size nor length method.
|
442
|
+
def repeated_permutation(n, &block)
|
443
|
+
delegate_to_array(:repeated_permutation, n, &block)
|
444
|
+
end
|
445
|
+
|
446
|
+
# Same as Array's.
|
447
|
+
# This method evaluates all elements of the class.
|
448
|
+
# This method raises NotImplementedError
|
449
|
+
# if the class provides neither size nor length method.
|
450
|
+
def reverse
|
451
|
+
delegate_to_array(:reverse)
|
452
|
+
end
|
453
|
+
|
454
|
+
# Same as Array's.
|
455
|
+
# This method evaluates elements of the class sequentially.
|
456
|
+
# This method raises NotImplementedError
|
457
|
+
# if the class provides neither size nor length method.
|
458
|
+
def reverse_each(&block)
|
459
|
+
# Needs size.
|
460
|
+
if block.nil?
|
461
|
+
Enumerator.new do |y|
|
462
|
+
(size - 1).downto 0 do |i|
|
463
|
+
y << at(i)
|
464
|
+
end
|
465
|
+
end
|
466
|
+
else
|
467
|
+
(size - 1).downto 0 do |i|
|
468
|
+
yield at(i)
|
469
|
+
end
|
470
|
+
end
|
471
|
+
end
|
472
|
+
|
473
|
+
# Same as Array's.
|
474
|
+
# This method evaluates minimum elements of the class.
|
475
|
+
# This method raises NotImplementedError
|
476
|
+
# if the class provides neither size nor length method.
|
477
|
+
def rindex(val = nil, &block)
|
478
|
+
i = 0
|
479
|
+
if block.nil?
|
480
|
+
reverse_each do |el|
|
481
|
+
i += 1
|
482
|
+
return size - i if el == val
|
483
|
+
end
|
484
|
+
else
|
485
|
+
reverse_each do |el|
|
486
|
+
i += 1
|
487
|
+
return size - i if block.call(el)
|
488
|
+
end
|
489
|
+
end
|
490
|
+
return nil
|
491
|
+
end
|
492
|
+
|
493
|
+
# Same as Array's.
|
494
|
+
# This method evaluates all elements of the class.
|
495
|
+
# This method raises NotImplementedError
|
496
|
+
# if the class provides neither size nor length method.
|
497
|
+
def rotate(cnt = 1)
|
498
|
+
delegate_to_array(:rotate, cnt)
|
499
|
+
end
|
500
|
+
|
501
|
+
# Same as Array's.
|
502
|
+
# This method evaluates one elements of the class if there is no argument.
|
503
|
+
# This method raises NotImplementedError
|
504
|
+
# if the class provides neither size nor length method.
|
505
|
+
def sample(*args)
|
506
|
+
# Needs size.
|
507
|
+
if args.size >= 2
|
508
|
+
raise ArgumentError, "wrong number of arguments (#{args.size} for 1..2)"
|
509
|
+
end
|
510
|
+
|
511
|
+
if args.size == 1
|
512
|
+
n = [args[0].to_int, size].min
|
513
|
+
return Enumerator.new do |y|
|
514
|
+
each_index do |i|
|
515
|
+
if n > 0 && rand(size - i) < n
|
516
|
+
y << at(i)
|
517
|
+
n -= 1
|
518
|
+
end
|
519
|
+
end
|
520
|
+
end.to_a.shuffle
|
521
|
+
else
|
522
|
+
if size == 0
|
523
|
+
return nil
|
524
|
+
else
|
525
|
+
return at(rand(size))
|
526
|
+
end
|
527
|
+
end
|
528
|
+
end
|
529
|
+
|
530
|
+
# Same as Array's.
|
531
|
+
# This method evaluates all elements of the class.
|
532
|
+
# This method raises NotImplementedError
|
533
|
+
# if the class provides neither size nor length method.
|
534
|
+
def shuffle
|
535
|
+
delegate_to_array(:shuffle)
|
536
|
+
end
|
537
|
+
|
538
|
+
alias :slice :[]
|
539
|
+
|
540
|
+
# sort is defined in Enumerable.
|
541
|
+
|
542
|
+
# Same as Array's.
|
543
|
+
# This method evaluates all elements of the class.
|
544
|
+
# This method raises NotImplementedError
|
545
|
+
# if the class provides neither size nor length method.
|
546
|
+
def transpose
|
547
|
+
delegate_to_array(:transpose)
|
548
|
+
end
|
549
|
+
|
550
|
+
# Same as Array's.
|
551
|
+
# This method evaluates all elements of the class.
|
552
|
+
# This method raises NotImplementedError
|
553
|
+
# if the class provides neither size nor length method.
|
554
|
+
def uniq(&block)
|
555
|
+
delegate_to_array(:uniq, &block)
|
556
|
+
end
|
557
|
+
|
558
|
+
# Same as Array's.
|
559
|
+
# This method evaluates minimum elements of the class.
|
560
|
+
# The arguments must not be negative values
|
561
|
+
# if the class does not provide size or length method.
|
562
|
+
def values_at(*selectors)
|
563
|
+
Enumerator.new do |y|
|
564
|
+
selectors.each do |s|
|
565
|
+
if s.is_a? Range
|
566
|
+
subary = self[s]
|
567
|
+
unless subary.nil?
|
568
|
+
self[s].each do |el|
|
569
|
+
y << el
|
570
|
+
end
|
571
|
+
end
|
572
|
+
if has_size? && !s.exclude_end? && s.include?(size)
|
573
|
+
y << nil
|
574
|
+
end
|
575
|
+
else
|
576
|
+
y << self[s.to_int]
|
577
|
+
end
|
578
|
+
end
|
579
|
+
end.to_a
|
580
|
+
end
|
581
|
+
|
582
|
+
# Same as Array's.
|
583
|
+
# This method evaluates all elements of the class.
|
584
|
+
# This method raises NotImplementedError
|
585
|
+
# if the class provides neither size nor length method.
|
586
|
+
def zip(*lists, &block)
|
587
|
+
delegate_to_array(:zip, *lists, &block)
|
588
|
+
end
|
589
|
+
|
590
|
+
# Same as Array's.
|
591
|
+
# This method evaluates all elements of the class.
|
592
|
+
# This method raises NotImplementedError
|
593
|
+
# if the class provides neither size nor length method.
|
594
|
+
def |(other)
|
595
|
+
delegate_to_array(:|, other)
|
596
|
+
end
|
597
|
+
|
598
|
+
end
|