Class LazyArray
In: lib/extlib/lazy_array.rb
Parent: Object
LazyArray dot/f_10.png

Methods

<<   ==   []   []=   add   any?   at   clear   concat   delete_at   delete_if   empty?   eql?   extract_slice_arguments   fetch   first   freeze   frozen?   include?   index   initialize_copy   insert   is_a?   kind_of?   last   lazy_load   lazy_possible?   load_with   loaded?   mark_loaded   method_missing   new   pop   push   replace   respond_to?   reverse   reverse!   shift   slice   slice!   splice   to_a   to_ary   unshift   values_at  

Attributes

head  [R] 
tail  [R] 

Public Class methods

[Source]

     # File lib/extlib/lazy_array.rb, line 394
394:   def initialize
395:     @load_with_proc = lambda { |v| v }
396:     @head           = []
397:     @tail           = []
398:     @array          = []
399:   end

Public Instance methods

[Source]

     # File lib/extlib/lazy_array.rb, line 181
181:   def <<(entry)
182:     if loaded?
183:       lazy_load
184:       @array << entry
185:     else
186:       @tail << entry
187:     end
188:     self
189:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 356
356:   def ==(other)
357:     return true if equal?(other)
358:     return false unless other.respond_to?(:to_ary)
359: 
360:     # if necessary, convert to something that can be compared
361:     other = other.to_ary unless other.respond_to?(:[])
362: 
363:     unless loaded?
364:       # compare the head against the beginning of other.  start at index
365:       # 0 and incrementally compare each entry. if other is a LazyArray
366:       # this has a lesser likelyhood of triggering a lazy load
367:       0.upto(@head.size - 1) do |i|
368:         return false unless @head[i] == other[i]
369:       end
370: 
371:       # compare the tail against the end of other.  start at index
372:       # -1 and decrementally compare each entry. if other is a LazyArray
373:       # this has a lesser likelyhood of triggering a lazy load
374:       -1.downto(@tail.size * -1) do |i|
375:         return false unless @tail[i] == other[i]
376:       end
377: 
378:       lazy_load
379:     end
380: 
381:     @array == other
382:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 106
106:   def [](*args)
107:     index, length = extract_slice_arguments(*args)
108: 
109:     if length.nil?
110:       return at(index)
111:     end
112: 
113:     length ||= 1
114: 
115:     if index >= 0 && lazy_possible?(@head, index + length)
116:       @head[*args]
117:     elsif index < 0 && lazy_possible?(@tail, index.abs - 1 + length)
118:       @tail[*args]
119:     else
120:       lazy_load
121:       @array[*args]
122:     end
123:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 142
142:   def []=(*args)
143:     index, length = extract_slice_arguments(*args[0..-2])
144: 
145:     length ||= 1
146: 
147:     if index >= 0 &&  lazy_possible?(@head, index + length)
148:       @head.[]=(*args)
149:     elsif index < 0 && lazy_possible?(@tail, index.abs - 1 + length)
150:       @tail.[]=(*args)
151:     else
152:       lazy_load
153:       @array.[]=(*args)
154:     end
155:   end
add(entry)

Alias for #<<

[Source]

     # File lib/extlib/lazy_array.rb, line 98
 98:   def any?(&block)
 99:     (lazy_possible?(@tail) && @tail.any?(&block)) ||
100:     (lazy_possible?(@head) && @head.any?(&block)) || begin
101:       lazy_load
102:       @array.any?(&block)
103:     end
104:   end

[Source]

    # File lib/extlib/lazy_array.rb, line 34
34:   def at(index)
35:     if index >= 0 && lazy_possible?(@head, index + 1)
36:       @head.at(index)
37:     elsif index < 0 && lazy_possible?(@tail, index.abs)
38:       @tail.at(index)
39:     else
40:       lazy_load
41:       @array.at(index)
42:     end
43:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 283
283:   def clear
284:     mark_loaded
285:     @array.clear
286:     self
287:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 193
193:   def concat(other)
194:     if loaded?
195:       lazy_load
196:       @array.concat(other)
197:     else
198:       @tail.concat(other)
199:     end
200:     self
201:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 253
253:   def delete_at(index)
254:     if index >= 0 && lazy_possible?(@head, index + 1)
255:       @head.delete_at(index)
256:     elsif index < 0 && lazy_possible?(@tail, index.abs)
257:       @tail.delete_at(index)
258:     else
259:       lazy_load
260:       @array.delete_at(index)
261:     end
262:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 264
264:   def delete_if(&block)
265:     if loaded?
266:       lazy_load
267:       @array.delete_if(&block)
268:     else
269:       @reapers ||= []
270:       @reapers << block
271:       @head.delete_if(&block)
272:       @tail.delete_if(&block)
273:     end
274:     self
275:   end

[Source]

    # File lib/extlib/lazy_array.rb, line 94
94:   def empty?
95:     !any?
96:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 330
330:   def eql?(other)
331:     return true if equal?(other)
332:     return false unless other.class.equal?(self.class)
333: 
334:     unless loaded?
335:       # compare the head against the beginning of other.  start at index
336:       # 0 and incrementally compare each entry. if other is a LazyArray
337:       # this has a lesser likelyhood of triggering a lazy load
338:       0.upto(@head.size - 1) do |i|
339:         return false unless @head[i].eql?(other[i])
340:       end
341: 
342:       # compare the tail against the end of other.  start at index
343:       # -1 and decrementally compare each entry. if other is a LazyArray
344:       # this has a lesser likelyhood of triggering a lazy load
345:       -1.downto(@tail.size * -1) do |i|
346:         return false unless @tail[i].eql?(other[i])
347:       end
348: 
349:       lazy_load
350:     end
351: 
352:     # convert other to an Array before checking equality
353:     @array.eql?(other.to_ary)
354:   end

[Source]

    # File lib/extlib/lazy_array.rb, line 45
45:   def fetch(*args, &block)
46:     index = args.first
47: 
48:     if index >= 0 && lazy_possible?(@head, index + 1)
49:       @head.fetch(*args, &block)
50:     elsif index < 0 && lazy_possible?(@tail, index.abs)
51:       @tail.fetch(*args, &block)
52:     else
53:       lazy_load
54:       @array.fetch(*args, &block)
55:     end
56:   end

[Source]

    # File lib/extlib/lazy_array.rb, line 16
16:   def first(*args)
17:     if lazy_possible?(@head, *args)
18:       @head.first(*args)
19:     else
20:       lazy_load
21:       @array.first(*args)
22:     end
23:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 315
315:   def freeze
316:     if loaded?
317:       @array.freeze
318:     else
319:       @head.freeze
320:       @tail.freeze
321:     end
322:     @frozen = true
323:     self
324:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 326
326:   def frozen?
327:     @frozen == true
328:   end

[Source]

    # File lib/extlib/lazy_array.rb, line 86
86:   def include?(entry)
87:     (lazy_possible?(@tail) && @tail.include?(entry)) ||
88:     (lazy_possible?(@head) && @head.include?(entry)) || begin
89:       lazy_load
90:       @array.include?(entry)
91:     end
92:   end

[Source]

    # File lib/extlib/lazy_array.rb, line 79
79:   def index(entry)
80:     (lazy_possible?(@head) && @head.index(entry)) || begin
81:       lazy_load
82:       @array.index(entry)
83:     end
84:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 223
223:   def insert(index, *entries)
224:     if index >= 0 && lazy_possible?(@head, index)
225:       @head.insert(index, *entries)
226:     elsif index < 0 && lazy_possible?(@tail, index.abs - 1)
227:       @tail.insert(index, *entries)
228:     else
229:       lazy_load
230:       @array.insert(index, *entries)
231:     end
232:     self
233:   end
is_a?(klass)

Alias for kind_of?

[Source]

     # File lib/extlib/lazy_array.rb, line 305
305:   def kind_of?(klass)
306:     super || @array.kind_of?(klass)
307:   end

[Source]

    # File lib/extlib/lazy_array.rb, line 25
25:   def last(*args)
26:     if lazy_possible?(@tail, *args)
27:       @tail.last(*args)
28:     else
29:       lazy_load
30:       @array.last(*args)
31:     end
32:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 296
296:   def load_with(&block)
297:     @load_with_proc = block
298:     self
299:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 301
301:   def loaded?
302:     @loaded == true
303:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 235
235:   def pop
236:     if lazy_possible?(@tail)
237:       @tail.pop
238:     else
239:       lazy_load
240:       @array.pop
241:     end
242:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 203
203:   def push(*entries)
204:     if loaded?
205:       lazy_load
206:       @array.push(*entries)
207:     else
208:       @tail.push(*entries)
209:     end
210:     self
211:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 277
277:   def replace(other)
278:     mark_loaded
279:     @array.replace(other)
280:     self
281:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 311
311:   def respond_to?(method, include_private = false)
312:     super || @array.respond_to?(method)
313:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 159
159:   def reverse
160:     dup.reverse!
161:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 163
163:   def reverse!
164:     # reverse without kicking if possible
165:     if loaded?
166:       @array = @array.reverse
167:     else
168:       @head, @tail = @tail.reverse, @head.reverse
169: 
170:       proc = @load_with_proc
171: 
172:       @load_with_proc = lambda do |v|
173:         proc.call(v)
174:         v.instance_variable_get(:@array).reverse!
175:       end
176:     end
177: 
178:     self
179:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 244
244:   def shift
245:     if lazy_possible?(@head)
246:       @head.shift
247:     else
248:       lazy_load
249:       @array.shift
250:     end
251:   end
slice(*args)

Alias for #[]

[Source]

     # File lib/extlib/lazy_array.rb, line 127
127:   def slice!(*args)
128:     index, length = extract_slice_arguments(*args)
129: 
130:     length ||= 1
131: 
132:     if index >= 0 && lazy_possible?(@head, index + length)
133:       @head.slice!(*args)
134:     elsif index < 0 && lazy_possible?(@tail, index.abs - 1 + length)
135:       @tail.slice!(*args)
136:     else
137:       lazy_load
138:       @array.slice!(*args)
139:     end
140:   end
splice(*args)

Alias for #[]=

[Source]

     # File lib/extlib/lazy_array.rb, line 289
289:   def to_a
290:     lazy_load
291:     @array.to_a
292:   end
to_ary()

Alias for to_a

[Source]

     # File lib/extlib/lazy_array.rb, line 213
213:   def unshift(*entries)
214:     if loaded?
215:       lazy_load
216:       @array.unshift(*entries)
217:     else
218:       @head.unshift(*entries)
219:     end
220:     self
221:   end

[Source]

    # File lib/extlib/lazy_array.rb, line 58
58:   def values_at(*args)
59:     accumulator = []
60: 
61:     lazy_possible = args.all? do |arg|
62:       index, length = extract_slice_arguments(arg)
63: 
64:       if index >= 0 && lazy_possible?(@head, index + (length || 1))
65:         accumulator.concat(head.values_at(*arg))
66:       elsif index < 0 && lazy_possible?(@tail, index.abs)
67:         accumulator.concat(tail.values_at(*arg))
68:       end
69:     end
70: 
71:     if lazy_possible
72:       accumulator
73:     else
74:       lazy_load
75:       @array.values_at(*args)
76:     end
77:   end

Protected Instance methods

[Source]

     # File lib/extlib/lazy_array.rb, line 388
388:   def lazy_possible?(list, need_length = 1)
389:     !loaded? && need_length <= list.size
390:   end

Private Instance methods

Extract arguments for slice an slice! and return index and length

@param [Integer, Array(Integer), Range] *args the index,

  index and length, or range indicating first and last position

@return [Integer] the index @return [Integer,NilClass] the length, if any

@api private

[Source]

     # File lib/extlib/lazy_array.rb, line 438
438:   def extract_slice_arguments(*args)
439:     first_arg, second_arg = args
440: 
441:     if args.size == 2 && first_arg.kind_of?(Integer) && second_arg.kind_of?(Integer)
442:       return first_arg, second_arg
443:     elsif args.size == 1
444:       if first_arg.kind_of?(Integer)
445:         return first_arg
446:       elsif first_arg.kind_of?(Range)
447:         index = first_arg.first
448:         length  = first_arg.last - index
449:         length += 1 unless first_arg.exclude_end?
450:         return index, length
451:       end
452:     end
453: 
454:     raise ArgumentError, "arguments may be 1 or 2 Integers, or 1 Range object, was: #{args.inspect}", caller(1)
455:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 401
401:   def initialize_copy(original)
402:     if original.loaded?
403:       mark_loaded
404:       @array = @array.dup
405:       @head = @tail = nil
406:     else
407:       @head  = @head.dup
408:       @tail  = @tail.dup
409:       @array = @array.dup
410:     end
411:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 413
413:   def lazy_load
414:     return if loaded?
415:     mark_loaded
416:     @load_with_proc[self]
417:     @array.unshift(*@head)
418:     @array.concat(@tail)
419:     @head = @tail = nil
420:     @reapers.each { |r| @array.delete_if(&r) } if @reapers
421:     @array.freeze if frozen?
422:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 424
424:   def mark_loaded
425:     @loaded = true
426:   end

delegate any not-explicitly-handled methods to @array, if possible. this is handy for handling methods mixed-into Array like group_by

[Source]

     # File lib/extlib/lazy_array.rb, line 459
459:   def method_missing(method, *args, &block)
460:     if @array.respond_to?(method)
461:       lazy_load
462:       results = @array.send(method, *args, &block)
463:       results.equal?(@array) ? self : results
464:     else
465:       super
466:     end
467:   end

[Validate]