random-accessible 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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