Class: LazyArray

Inherits:
Object show all
Includes:
Enumerable
Defined in:
lib/extlib/lazy_array.rb

Overview

borrowed partially from StrokeDB

Instance Attribute Summary collapse

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object (private)

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



422
423
424
425
426
427
428
429
430
# File 'lib/extlib/lazy_array.rb', line 422

def method_missing(method, *args, &block)
  if @array.respond_to?(method)
    lazy_load
    results = @array.send(method, *args, &block)
    results.equal?(@array) ? self : results
  else
    super
  end
end

Instance Attribute Details

#headObject (readonly)

Returns the value of attribute head.



6
7
8
# File 'lib/extlib/lazy_array.rb', line 6

def head
  @head
end

#tailObject (readonly)

Returns the value of attribute tail.



6
7
8
# File 'lib/extlib/lazy_array.rb', line 6

def tail
  @tail
end

Instance Method Details

#<<(entry) ⇒ Object



171
172
173
174
175
176
177
178
179
# File 'lib/extlib/lazy_array.rb', line 171

def <<(entry)
  if loaded?
    lazy_load
    @array << entry
  else
    @tail << entry
  end
  self
end

#==(other) ⇒ Object



317
318
319
320
321
322
323
324
325
326
327
328
329
330
# File 'lib/extlib/lazy_array.rb', line 317

def ==(other)
  if equal?(other)
    return true
  end

  unless other.respond_to?(:to_ary)
    return false
  end

  # if necessary, convert to something that can be compared
  other = other.to_ary unless other.respond_to?(:[])

  cmp?(other, :==)
end

#[](*args) ⇒ Object Also known as: slice



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/extlib/lazy_array.rb', line 102

def [](*args)
  index, length = extract_slice_arguments(*args)

  if length == 1 && args.size == 1 && args.first.kind_of?(Integer)
    return at(index)
  end

  if index >= 0 && lazy_possible?(@head, index + length)
    @head[*args]
  elsif index < 0 && lazy_possible?(@tail, index.abs - 1 + length)
    @tail[*args]
  else
    lazy_load
    @array[*args]
  end
end

#[]=(*args) ⇒ Object Also known as: splice



134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/extlib/lazy_array.rb', line 134

def []=(*args)
  index, length = extract_slice_arguments(*args[0..-2])

  if index >= 0 && lazy_possible?(@head, index + length)
    @head.[]=(*args)
  elsif index < 0 && lazy_possible?(@tail, index.abs - 1 + length)
    @tail.[]=(*args)
  else
    lazy_load
    @array.[]=(*args)
  end
end

#any?(&block) ⇒ Boolean

Returns:

  • (Boolean)


94
95
96
97
98
99
100
# File 'lib/extlib/lazy_array.rb', line 94

def any?(&block)
  (lazy_possible?(@tail) && @tail.any?(&block)) ||
  (lazy_possible?(@head) && @head.any?(&block)) || begin
    lazy_load
    @array.any?(&block)
  end
end

#at(index) ⇒ Object



26
27
28
29
30
31
32
33
34
35
# File 'lib/extlib/lazy_array.rb', line 26

def at(index)
  if index >= 0 && lazy_possible?(@head, index + 1)
    @head.at(index)
  elsif index < 0 && lazy_possible?(@tail, index.abs)
    @tail.at(index)
  else
    lazy_load
    @array.at(index)
  end
end

#clearObject



270
271
272
273
274
# File 'lib/extlib/lazy_array.rb', line 270

def clear
  mark_loaded
  @array.clear
  self
end

#concat(other) ⇒ Object



181
182
183
184
185
186
187
188
189
# File 'lib/extlib/lazy_array.rb', line 181

def concat(other)
  if loaded?
    lazy_load
    @array.concat(other)
  else
    @tail.concat(other)
  end
  self
end

#delete_at(index) ⇒ Object



241
242
243
244
245
246
247
248
249
250
# File 'lib/extlib/lazy_array.rb', line 241

def delete_at(index)
  if index >= 0 && lazy_possible?(@head, index + 1)
    @head.delete_at(index)
  elsif index < 0 && lazy_possible?(@tail, index.abs)
    @tail.delete_at(index)
  else
    lazy_load
    @array.delete_at(index)
  end
end

#delete_if(&block) ⇒ Object



252
253
254
255
256
257
258
259
260
261
262
# File 'lib/extlib/lazy_array.rb', line 252

def delete_if(&block)
  if loaded?
    lazy_load
    @array.delete_if(&block)
  else
    @reapers << block
    @head.delete_if(&block)
    @tail.delete_if(&block)
  end
  self
end

#empty?Boolean

Returns:

  • (Boolean)


86
87
88
89
90
91
92
# File 'lib/extlib/lazy_array.rb', line 86

def empty?
  (@tail.nil? || @tail.empty?) &&
  (@head.nil? || @head.empty?) && begin
    lazy_load
    @array.empty?
  end
end

#eql?(other) ⇒ Boolean

Returns:

  • (Boolean)


332
333
334
335
336
337
338
339
340
341
342
# File 'lib/extlib/lazy_array.rb', line 332

def eql?(other)
  if equal?(other)
    return true
  end

  unless other.class.equal?(self.class)
    return false
  end

  cmp?(other, :eql?)
end

#fetch(*args, &block) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/extlib/lazy_array.rb', line 37

def fetch(*args, &block)
  index = args.first

  if index >= 0 && lazy_possible?(@head, index + 1)
    @head.fetch(*args, &block)
  elsif index < 0 && lazy_possible?(@tail, index.abs)
    @tail.fetch(*args, &block)
  else
    lazy_load
    @array.fetch(*args, &block)
  end
end

#first(*args) ⇒ Object



8
9
10
11
12
13
14
15
# File 'lib/extlib/lazy_array.rb', line 8

def first(*args)
  if lazy_possible?(@head, *args)
    @head.first(*args)
  else
    lazy_load
    @array.first(*args)
  end
end

#freezeObject



302
303
304
305
306
307
308
309
310
311
# File 'lib/extlib/lazy_array.rb', line 302

def freeze
  if loaded?
    @array.freeze
  else
    @head.freeze
    @tail.freeze
  end
  @frozen = true
  self
end

#frozen?Boolean

Returns:

  • (Boolean)


313
314
315
# File 'lib/extlib/lazy_array.rb', line 313

def frozen?
  @frozen == true
end

#include?(entry) ⇒ Boolean

Returns:

  • (Boolean)


78
79
80
81
82
83
84
# File 'lib/extlib/lazy_array.rb', line 78

def include?(entry)
  (lazy_possible?(@tail) && @tail.include?(entry)) ||
  (lazy_possible?(@head) && @head.include?(entry)) || begin
    lazy_load
    @array.include?(entry)
  end
end

#index(entry) ⇒ Object



71
72
73
74
75
76
# File 'lib/extlib/lazy_array.rb', line 71

def index(entry)
  (lazy_possible?(@head) && @head.index(entry)) || begin
    lazy_load
    @array.index(entry)
  end
end

#insert(index, *entries) ⇒ Object



211
212
213
214
215
216
217
218
219
220
221
# File 'lib/extlib/lazy_array.rb', line 211

def insert(index, *entries)
  if index >= 0 && lazy_possible?(@head, index)
    @head.insert(index, *entries)
  elsif index < 0 && lazy_possible?(@tail, index.abs - 1)
    @tail.insert(index, *entries)
  else
    lazy_load
    @array.insert(index, *entries)
  end
  self
end

#kind_of?(klass) ⇒ Boolean Also known as: is_a?

Returns:

  • (Boolean)


292
293
294
# File 'lib/extlib/lazy_array.rb', line 292

def kind_of?(klass)
  super || @array.kind_of?(klass)
end

#last(*args) ⇒ Object



17
18
19
20
21
22
23
24
# File 'lib/extlib/lazy_array.rb', line 17

def last(*args)
  if lazy_possible?(@tail, *args)
    @tail.last(*args)
  else
    lazy_load
    @array.last(*args)
  end
end

#lazy_possible?(list, need_length = 1) ⇒ Boolean

Returns:

  • (Boolean)


344
345
346
# File 'lib/extlib/lazy_array.rb', line 344

def lazy_possible?(list, need_length = 1)
  !loaded? && need_length <= list.size
end

#load_with(&block) ⇒ Object



283
284
285
286
# File 'lib/extlib/lazy_array.rb', line 283

def load_with(&block)
  @load_with_proc = block
  self
end

#loaded?Boolean

Returns:

  • (Boolean)


288
289
290
# File 'lib/extlib/lazy_array.rb', line 288

def loaded?
  @loaded == true
end

#pop(*args) ⇒ Object



223
224
225
226
227
228
229
230
# File 'lib/extlib/lazy_array.rb', line 223

def pop(*args)
  if lazy_possible?(@tail, *args)
    @tail.pop(*args)
  else
    lazy_load
    @array.pop(*args)
  end
end

#push(*entries) ⇒ Object



191
192
193
194
195
196
197
198
199
# File 'lib/extlib/lazy_array.rb', line 191

def push(*entries)
  if loaded?
    lazy_load
    @array.push(*entries)
  else
    @tail.push(*entries)
  end
  self
end

#replace(other) ⇒ Object



264
265
266
267
268
# File 'lib/extlib/lazy_array.rb', line 264

def replace(other)
  mark_loaded
  @array.replace(other)
  self
end

#respond_to?(method, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


298
299
300
# File 'lib/extlib/lazy_array.rb', line 298

def respond_to?(method, include_private = false)
  super || @array.respond_to?(method)
end

#reverseObject



149
150
151
# File 'lib/extlib/lazy_array.rb', line 149

def reverse
  dup.reverse!
end

#reverse!Object



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/extlib/lazy_array.rb', line 153

def reverse!
  # reverse without kicking if possible
  if loaded?
    @array = @array.reverse
  else
    @head, @tail = @tail.reverse, @head.reverse

    proc = @load_with_proc

    @load_with_proc = lambda do |v|
      proc.call(v)
      v.instance_variable_get(:@array).reverse!
    end
  end

  self
end

#shift(*args) ⇒ Object



232
233
234
235
236
237
238
239
# File 'lib/extlib/lazy_array.rb', line 232

def shift(*args)
  if lazy_possible?(@head, *args)
    @head.shift(*args)
  else
    lazy_load
    @array.shift(*args)
  end
end

#slice!(*args) ⇒ Object



121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/extlib/lazy_array.rb', line 121

def slice!(*args)
  index, length = extract_slice_arguments(*args)

  if index >= 0 && lazy_possible?(@head, index + length)
    @head.slice!(*args)
  elsif index < 0 && lazy_possible?(@tail, index.abs - 1 + length)
    @tail.slice!(*args)
  else
    lazy_load
    @array.slice!(*args)
  end
end

#to_aObject Also known as: to_ary



276
277
278
279
# File 'lib/extlib/lazy_array.rb', line 276

def to_a
  lazy_load
  @array.to_a
end

#unshift(*entries) ⇒ Object



201
202
203
204
205
206
207
208
209
# File 'lib/extlib/lazy_array.rb', line 201

def unshift(*entries)
  if loaded?
    lazy_load
    @array.unshift(*entries)
  else
    @head.unshift(*entries)
  end
  self
end

#values_at(*args) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/extlib/lazy_array.rb', line 50

def values_at(*args)
  accumulator = []

  lazy_possible = args.all? do |arg|
    index, length = extract_slice_arguments(arg)

    if index >= 0 && lazy_possible?(@head, index + length)
      accumulator.concat(head.values_at(*arg))
    elsif index < 0 && lazy_possible?(@tail, index.abs)
      accumulator.concat(tail.values_at(*arg))
    end
  end

  if lazy_possible
    accumulator
  else
    lazy_load
    @array.values_at(*args)
  end
end