class LazyArray

Attributes

head[R]
tail[R]

Public Class Methods

new() click to toggle source
# File lib/ardm/support/lazy_array.rb, line 348
def initialize
  @frozen         = false
  @loaded         = false
  @load_with_proc = lambda { |v| v }
  @head           = []
  @tail           = []
  @array          = []
  @reapers        = []
end

Public Instance Methods

<<(entry) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 169
def <<(entry)
  if loaded?
    lazy_load
    @array << entry
  else
    @tail << entry
  end
  self
end
==(other) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 315
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) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 100
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
Also aliased as: slice
[]=(*args) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 132
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
Also aliased as: splice
any?(&block) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 92
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) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 24
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
clear() click to toggle source
# File lib/ardm/support/lazy_array.rb, line 268
def clear
  mark_loaded
  @array.clear
  self
end
concat(other) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 179
def concat(other)
  if loaded?
    lazy_load
    @array.concat(other)
  else
    @tail.concat(other)
  end
  self
end
delete_at(index) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 239
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) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 250
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?() click to toggle source
# File lib/ardm/support/lazy_array.rb, line 84
def empty?
  (@tail.nil? || @tail.empty?) &&
  (@head.nil? || @head.empty?) && begin
    lazy_load
    @array.empty?
  end
end
eql?(other) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 330
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) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 35
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) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 6
def first(*args)
  if lazy_possible?(@head, *args)
    @head.first(*args)
  else
    lazy_load
    @array.first(*args)
  end
end
freeze() click to toggle source
# File lib/ardm/support/lazy_array.rb, line 300
def freeze
  if loaded?
    @array.freeze
  else
    @head.freeze
    @tail.freeze
  end
  @frozen = true
  self
end
frozen?() click to toggle source
# File lib/ardm/support/lazy_array.rb, line 311
def frozen?
  @frozen == true
end
include?(entry) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 76
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) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 69
def index(entry)
  (lazy_possible?(@head) && @head.index(entry)) || begin
    lazy_load
    @array.index(entry)
  end
end
insert(index, *entries) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 209
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
is_a?(klass)
Alias for: kind_of?
kind_of?(klass) click to toggle source
Calls superclass method
# File lib/ardm/support/lazy_array.rb, line 290
def kind_of?(klass)
  super || @array.kind_of?(klass)
end
Also aliased as: is_a?
last(*args) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 15
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) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 342
def lazy_possible?(list, need_length = 1)
  !loaded? && need_length <= list.size
end
load_with(&block) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 281
def load_with(&block)
  @load_with_proc = block
  self
end
loaded?() click to toggle source
# File lib/ardm/support/lazy_array.rb, line 286
def loaded?
  @loaded == true
end
pop(*args) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 221
def pop(*args)
  if lazy_possible?(@tail, *args)
    @tail.pop(*args)
  else
    lazy_load
    @array.pop(*args)
  end
end
push(*entries) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 189
def push(*entries)
  if loaded?
    lazy_load
    @array.push(*entries)
  else
    @tail.push(*entries)
  end
  self
end
replace(other) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 262
def replace(other)
  mark_loaded
  @array.replace(other)
  self
end
respond_to?(method, include_private = false) click to toggle source
Calls superclass method
# File lib/ardm/support/lazy_array.rb, line 296
def respond_to?(method, include_private = false)
  super || @array.respond_to?(method)
end
reverse() click to toggle source
# File lib/ardm/support/lazy_array.rb, line 147
def reverse
  dup.reverse!
end
reverse!() click to toggle source
# File lib/ardm/support/lazy_array.rb, line 151
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) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 230
def shift(*args)
  if lazy_possible?(@head, *args)
    @head.shift(*args)
  else
    lazy_load
    @array.shift(*args)
  end
end
slice(*args)
Alias for: []
slice!(*args) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 119
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
splice(*args)
Alias for: []=
to_a() click to toggle source
# File lib/ardm/support/lazy_array.rb, line 274
def to_a
  lazy_load
  @array.to_a
end
Also aliased as: to_ary
to_ary()
Alias for: to_a
unshift(*entries) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 199
def unshift(*entries)
  if loaded?
    lazy_load
    @array.unshift(*entries)
  else
    @head.unshift(*entries)
  end
  self
end
values_at(*args) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 48
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

Private Instance Methods

cmp?(other, operator) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 430
def cmp?(other, operator)
  unless loaded?
    # compare the head against the beginning of other.  start at index
    # 0 and incrementally compare each entry. if other is a LazyArray
    # this has a lesser likelyhood of triggering a lazy load
    0.upto(@head.size - 1) do |i|
      return false unless @head[i].__send__(operator, other[i])
    end

    # compare the tail against the end of other.  start at index
    # -1 and decrementally compare each entry. if other is a LazyArray
    # this has a lesser likelyhood of triggering a lazy load
    -1.downto(@tail.size * -1) do |i|
      return false unless @tail[i].__send__(operator, other[i])
    end

    lazy_load
  end

  @array.send(operator, other.to_ary)
end
each() { |entry| ... } click to toggle source
# File lib/ardm/support/lazy_array.rb, line 408
def each
  lazy_load
  if block_given?
    @array.each { |entry| yield entry }
    self
  else
    @array.each
  end
end
extract_slice_arguments(*args) click to toggle source

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

# File lib/ardm/support/lazy_array.rb, line 389
def extract_slice_arguments(*args)
  first_arg, second_arg = args

  if args.size == 2 && first_arg.kind_of?(Integer) && second_arg.kind_of?(Integer)
    return first_arg, second_arg
  elsif args.size == 1
    if first_arg.kind_of?(Integer)
      return first_arg, 1
    elsif first_arg.kind_of?(Range)
      index = first_arg.first
      length  = first_arg.last - index
      length += 1 unless first_arg.exclude_end?
      return index, length
    end
  end

  raise ArgumentError, "arguments may be 1 or 2 Integers, or 1 Range object, was: #{args.inspect}", caller(1)
end
initialize_copy(original) click to toggle source
# File lib/ardm/support/lazy_array.rb, line 358
def initialize_copy(original)
  @head  = Ardm::Ext.try_dup(@head)
  @tail  = Ardm::Ext.try_dup(@tail)
  @array = Ardm::Ext.try_dup(@array)
end
lazy_load() click to toggle source
# File lib/ardm/support/lazy_array.rb, line 364
def lazy_load
  return if loaded?
  mark_loaded
  @load_with_proc[self]
  @array.unshift(*@head)
  @array.concat(@tail)
  @head = @tail = nil
  @reapers.each { |r| @array.delete_if(&r) } if @reapers
  @array.freeze if frozen?
end
mark_loaded() click to toggle source
# File lib/ardm/support/lazy_array.rb, line 375
def mark_loaded
  @loaded = true
end
method_missing(method, *args, &block) click to toggle source

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

Calls superclass method Ardm::Ar::Relation#method_missing
# File lib/ardm/support/lazy_array.rb, line 420
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