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

Methods

<<   ==   []   []=   any?   at   clear   cmp?   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 344
344:   def initialize
345:     @frozen         = false
346:     @loaded         = false
347:     @load_with_proc = lambda { |v| v }
348:     @head           = []
349:     @tail           = []
350:     @array          = []
351:     @reapers        = []
352:   end

Public Instance methods

[Source]

     # File lib/extlib/lazy_array.rb, line 165
165:   def <<(entry)
166:     if loaded?
167:       lazy_load
168:       @array << entry
169:     else
170:       @tail << entry
171:     end
172:     self
173:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 311
311:   def ==(other)
312:     if equal?(other)
313:       return true
314:     end
315: 
316:     unless other.respond_to?(:to_ary)
317:       return false
318:     end
319: 
320:     # if necessary, convert to something that can be compared
321:     other = other.to_ary unless other.respond_to?(:[])
322: 
323:     cmp?(other, :==)
324:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 96
 96:   def [](*args)
 97:     index, length = extract_slice_arguments(*args)
 98: 
 99:     if length == 1 && args.size == 1 && args.first.kind_of?(Integer)
100:       return at(index)
101:     end
102: 
103:     if index >= 0 && lazy_possible?(@head, index + length)
104:       @head[*args]
105:     elsif index < 0 && lazy_possible?(@tail, index.abs - 1 + length)
106:       @tail[*args]
107:     else
108:       lazy_load
109:       @array[*args]
110:     end
111:   end

[Source]

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

[Source]

    # File lib/extlib/lazy_array.rb, line 88
88:   def any?(&block)
89:     (lazy_possible?(@tail) && @tail.any?(&block)) ||
90:     (lazy_possible?(@head) && @head.any?(&block)) || begin
91:       lazy_load
92:       @array.any?(&block)
93:     end
94:   end

[Source]

    # File lib/extlib/lazy_array.rb, line 24
24:   def at(index)
25:     if index >= 0 && lazy_possible?(@head, index + 1)
26:       @head.at(index)
27:     elsif index < 0 && lazy_possible?(@tail, index.abs)
28:       @tail.at(index)
29:     else
30:       lazy_load
31:       @array.at(index)
32:     end
33:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 264
264:   def clear
265:     mark_loaded
266:     @array.clear
267:     self
268:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 175
175:   def concat(other)
176:     if loaded?
177:       lazy_load
178:       @array.concat(other)
179:     else
180:       @tail.concat(other)
181:     end
182:     self
183:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 235
235:   def delete_at(index)
236:     if index >= 0 && lazy_possible?(@head, index + 1)
237:       @head.delete_at(index)
238:     elsif index < 0 && lazy_possible?(@tail, index.abs)
239:       @tail.delete_at(index)
240:     else
241:       lazy_load
242:       @array.delete_at(index)
243:     end
244:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 246
246:   def delete_if(&block)
247:     if loaded?
248:       lazy_load
249:       @array.delete_if(&block)
250:     else
251:       @reapers << block
252:       @head.delete_if(&block)
253:       @tail.delete_if(&block)
254:     end
255:     self
256:   end

[Source]

    # File lib/extlib/lazy_array.rb, line 84
84:   def empty?
85:     !any?
86:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 326
326:   def eql?(other)
327:     if equal?(other)
328:       return true
329:     end
330: 
331:     unless other.class.equal?(self.class)
332:       return false
333:     end
334: 
335:     cmp?(other, :eql?)
336:   end

[Source]

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

[Source]

    # File lib/extlib/lazy_array.rb, line 6
 6:   def first(*args)
 7:     if lazy_possible?(@head, *args)
 8:       @head.first(*args)
 9:     else
10:       lazy_load
11:       @array.first(*args)
12:     end
13:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 296
296:   def freeze
297:     if loaded?
298:       @array.freeze
299:     else
300:       @head.freeze
301:       @tail.freeze
302:     end
303:     @frozen = true
304:     self
305:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 307
307:   def frozen?
308:     @frozen == true
309:   end

[Source]

    # File lib/extlib/lazy_array.rb, line 76
76:   def include?(entry)
77:     (lazy_possible?(@tail) && @tail.include?(entry)) ||
78:     (lazy_possible?(@head) && @head.include?(entry)) || begin
79:       lazy_load
80:       @array.include?(entry)
81:     end
82:   end

[Source]

    # File lib/extlib/lazy_array.rb, line 69
69:   def index(entry)
70:     (lazy_possible?(@head) && @head.index(entry)) || begin
71:       lazy_load
72:       @array.index(entry)
73:     end
74:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 205
205:   def insert(index, *entries)
206:     if index >= 0 && lazy_possible?(@head, index)
207:       @head.insert(index, *entries)
208:     elsif index < 0 && lazy_possible?(@tail, index.abs - 1)
209:       @tail.insert(index, *entries)
210:     else
211:       lazy_load
212:       @array.insert(index, *entries)
213:     end
214:     self
215:   end
is_a?(klass)

Alias for kind_of?

[Source]

     # File lib/extlib/lazy_array.rb, line 286
286:   def kind_of?(klass)
287:     super || @array.kind_of?(klass)
288:   end

[Source]

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

[Source]

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

[Source]

     # File lib/extlib/lazy_array.rb, line 277
277:   def load_with(&block)
278:     @load_with_proc = block
279:     self
280:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 282
282:   def loaded?
283:     @loaded == true
284:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 217
217:   def pop
218:     if lazy_possible?(@tail)
219:       @tail.pop
220:     else
221:       lazy_load
222:       @array.pop
223:     end
224:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 185
185:   def push(*entries)
186:     if loaded?
187:       lazy_load
188:       @array.push(*entries)
189:     else
190:       @tail.push(*entries)
191:     end
192:     self
193:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 258
258:   def replace(other)
259:     mark_loaded
260:     @array.replace(other)
261:     self
262:   end

[Source]

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

[Source]

     # File lib/extlib/lazy_array.rb, line 143
143:   def reverse
144:     dup.reverse!
145:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 147
147:   def reverse!
148:     # reverse without kicking if possible
149:     if loaded?
150:       @array = @array.reverse
151:     else
152:       @head, @tail = @tail.reverse, @head.reverse
153: 
154:       proc = @load_with_proc
155: 
156:       @load_with_proc = lambda do |v|
157:         proc.call(v)
158:         v.instance_variable_get(:@array).reverse!
159:       end
160:     end
161: 
162:     self
163:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 226
226:   def shift
227:     if lazy_possible?(@head)
228:       @head.shift
229:     else
230:       lazy_load
231:       @array.shift
232:     end
233:   end
slice(*args)

Alias for #[]

[Source]

     # File lib/extlib/lazy_array.rb, line 115
115:   def slice!(*args)
116:     index, length = extract_slice_arguments(*args)
117: 
118:     if index >= 0 && lazy_possible?(@head, index + length)
119:       @head.slice!(*args)
120:     elsif index < 0 && lazy_possible?(@tail, index.abs - 1 + length)
121:       @tail.slice!(*args)
122:     else
123:       lazy_load
124:       @array.slice!(*args)
125:     end
126:   end
splice(*args)

Alias for #[]=

[Source]

     # File lib/extlib/lazy_array.rb, line 270
270:   def to_a
271:     lazy_load
272:     @array.to_a
273:   end
to_ary()

Alias for to_a

[Source]

     # File lib/extlib/lazy_array.rb, line 195
195:   def unshift(*entries)
196:     if loaded?
197:       lazy_load
198:       @array.unshift(*entries)
199:     else
200:       @head.unshift(*entries)
201:     end
202:     self
203:   end

[Source]

    # File lib/extlib/lazy_array.rb, line 48
48:   def values_at(*args)
49:     accumulator = []
50: 
51:     lazy_possible = args.all? do |arg|
52:       index, length = extract_slice_arguments(arg)
53: 
54:       if index >= 0 && lazy_possible?(@head, index + length)
55:         accumulator.concat(head.values_at(*arg))
56:       elsif index < 0 && lazy_possible?(@tail, index.abs)
57:         accumulator.concat(tail.values_at(*arg))
58:       end
59:     end
60: 
61:     if lazy_possible
62:       accumulator
63:     else
64:       lazy_load
65:       @array.values_at(*args)
66:     end
67:   end

Private Instance methods

[Source]

     # File lib/extlib/lazy_array.rb, line 416
416:   def cmp?(other, operator)
417:     unless loaded?
418:       # compare the head against the beginning of other.  start at index
419:       # 0 and incrementally compare each entry. if other is a LazyArray
420:       # this has a lesser likelyhood of triggering a lazy load
421:       0.upto(@head.size - 1) do |i|
422:         return false unless @head[i].send(operator, other[i])
423:       end
424: 
425:       # compare the tail against the end of other.  start at index
426:       # -1 and decrementally compare each entry. if other is a LazyArray
427:       # this has a lesser likelyhood of triggering a lazy load
428:       -1.downto(@tail.size * -1) do |i|
429:         return false unless @tail[i].send(operator, other[i])
430:       end
431: 
432:       lazy_load
433:     end
434: 
435:     @array.send(operator, other.to_ary)
436:   end

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 385
385:   def extract_slice_arguments(*args)
386:     first_arg, second_arg = args
387: 
388:     if args.size == 2 && first_arg.kind_of?(Integer) && second_arg.kind_of?(Integer)
389:       return first_arg, second_arg
390:     elsif args.size == 1
391:       if first_arg.kind_of?(Integer)
392:         return first_arg, 1
393:       elsif first_arg.kind_of?(Range)
394:         index = first_arg.first
395:         length  = first_arg.last - index
396:         length += 1 unless first_arg.exclude_end?
397:         return index, length
398:       end
399:     end
400: 
401:     raise ArgumentError, "arguments may be 1 or 2 Integers, or 1 Range object, was: #{args.inspect}", caller(1)
402:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 354
354:   def initialize_copy(original)
355:     @head  = @head.try_dup
356:     @tail  = @tail.try_dup
357:     @array = @array.try_dup
358:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 360
360:   def lazy_load
361:     return if loaded?
362:     mark_loaded
363:     @load_with_proc[self]
364:     @array.unshift(*@head)
365:     @array.concat(@tail)
366:     @head = @tail = nil
367:     @reapers.each { |r| @array.delete_if(&r) } if @reapers
368:     @array.freeze if frozen?
369:   end

[Source]

     # File lib/extlib/lazy_array.rb, line 371
371:   def mark_loaded
372:     @loaded = true
373:   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 406
406:   def method_missing(method, *args, &block)
407:     if @array.respond_to?(method)
408:       lazy_load
409:       results = @array.send(method, *args, &block)
410:       results.equal?(@array) ? self : results
411:     else
412:       super
413:     end
414:   end

[Validate]