random-accessible 0.1.2 → 0.1.3

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