Class: Laziest::ArrayPromise

Inherits:
Promise
  • Object
show all
Defined in:
lib/laziest/array.rb

Overview

This class is a lazily-evaluated array based on an enumerator. A contract: The enumerator is guaranteed to never be rewound.

Instance Method Summary collapse

Constructor Details

#initialize(enumerator, array = [], nil_on_empty = false) ⇒ ArrayPromise

Accepts ‘array’ to allow a partially-evaluated enumerator/array to initialize.



6
7
8
9
10
11
12
13
14
15
16
17
18
# File 'lib/laziest/array.rb', line 6

def initialize enumerator, array=[], nil_on_empty = false
  @array = array
  @enumerator = enumerator
  @nil_on_empty = nil_on_empty
  super() do
    ::Kernel.loop do
      @array << @enumerator.next
    end
    @enumerator = nil
    # Needed for use in hashes, like group_by
    (nil_on_empty && @array.empty?) ? nil : @array
  end
end

Instance Method Details

#[](index, length = nil) ⇒ Object

Array-related laziness



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/laziest/array.rb', line 33

def [] index, length=nil
  return super if __forced__?
  if length.nil?
    if index.kind_of? ::Range
      enum = ::Enumerator.new do |y|
        index.each do |i|
          y << self[i]
        end
      end
      ArrayPromise.new enum
    else
      __force_to__ index
      @array[index]
    end
  else
    enum = ::Enumerator.new do |y|
      i = index
      length.times do
        y << self[i]
        i += 1
      end
    end
    ArrayPromise.new enum
  end
end

#__force_to__(index) ⇒ Object



59
60
61
62
63
64
65
66
67
68
# File 'lib/laziest/array.rb', line 59

def __force_to__ index
  begin
    @mutex.synchronize do
      while @array.length <= index
        @array << @enumerator.next
      end
    end
  rescue ::StopIteration
  end
end

#__forced__?Boolean

Returns:

  • (Boolean)


70
71
72
73
74
75
76
77
78
79
# File 'lib/laziest/array.rb', line 70

def __forced__?
  if @nil_on_empty && @array.empty?
    # Check if we're really empty.
    __force_to__ 1
    # Either we'll be empty (and finalized as nil), so we'll revert to
    # calling super which forwards to nil and so on,
    # or we'll be nonempty (and normal logic proceeds)
  end
  !(@result.equal?(NOT_SET) && @error.equal?(NOT_SET))
end

#each(&block) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
# File 'lib/laziest/array.rb', line 20

def each(&block)
  return super if __forced__?
  return ::Enumerator.new{|y| each {|x| y << x}}.lazy unless ::Kernel.block_given?
  index = 0
  ::Kernel.loop do
    __force_to__ index
    break unless @array.length > index
    yield @array[index]
    index += 1
  end
end

#to_aObject

Except this one, make it a no-op. (Also should prevent infinite recursion.)



104
105
106
107
# File 'lib/laziest/array.rb', line 104

def to_a
  return super if __forced__?
  self
end