random-accessible 0.1.2 → 0.1.3

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.
@@ -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