Class: ThinModels::LazyArray
- Inherits:
-
Object
- Object
- ThinModels::LazyArray
- Includes:
- Enumerable
- Defined in:
- lib/thin_models/lazy_array.rb
Overview
Exposes Enumerable and a subset of the interface of Array, but is lazily evaluated.
The default constructor allows you to pass in an underlying Enumerable whose .each method will be used; or you can ignore this and override #each and #initialize yourself.
You should also consider overriding #length if you have an optimised mechanism for evaluating it without doing a full iteration via #each, and overriding #slice_from_start_and_length if you have an optimised mechanism for iterating over a slice/sub-range of the array. This will be used to supply optimised versions of #[] / #slice
Deliberately doesn’t expose any mutation methods - is not intended to be a mutable data structure.
Direct Known Subclasses
Defined Under Namespace
Classes: Mapped, Memoized, MemoizedLength
Instance Method Summary collapse
-
#[](index_or_range, length = nil) ⇒ Object
(also: #slice)
behaviour is consistent with Array#[], except it doesn’t take negative indexes.
- #each(&b) ⇒ Object
- #empty? ⇒ Boolean
- #first ⇒ Object
-
#initialize(enumerable = nil) ⇒ LazyArray
constructor
A new instance of LazyArray.
- #inspect ⇒ Object
- #join(separator = $,) ⇒ Object
- #last ⇒ Object
-
#length ⇒ Object
We recommend overriding this #length implementation (which is based on #each) with an efficient implementation.
-
#map(memoize = false, &b) ⇒ Object
map works lazily, resulting in a ThinModels::LazyArray::Mapped or a ThinModels::LazyArray::Memoized::Mapped (which additionally memoizes the mapped values).
- #size ⇒ Object
-
#slice_from_start_and_length(start, length) ⇒ Object
We recommend overriding this inefficient implementation (which uses #each to traverse from the start until it reaches the desired range) with an efficient implementation.
- #to_json(*p) ⇒ Object
Constructor Details
#initialize(enumerable = nil) ⇒ LazyArray
Returns a new instance of LazyArray.
16 17 18 |
# File 'lib/thin_models/lazy_array.rb', line 16 def initialize(enumerable=nil) @enumerable = enumerable end |
Instance Method Details
#[](index_or_range, length = nil) ⇒ Object Also known as: slice
behaviour is consistent with Array#[], except it doesn’t take negative indexes. uses slice_from_start_and_length to do the work.
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/thin_models/lazy_array.rb', line 85 def [](index_or_range, length=nil) case index_or_range when Range start = index_or_range.begin length = index_or_range.end - start length += 1 unless index_or_range.exclude_end? slice_from_start_and_length(start, length) when Integer if length slice_from_start_and_length(index_or_range, length) else slice = slice_from_start_and_length(index_or_range, 1) and slice.first end else raise ArgumentError end end |
#each(&b) ⇒ Object
20 21 22 |
# File 'lib/thin_models/lazy_array.rb', line 20 def each(&b) @enumerable.each(&b) end |
#empty? ⇒ Boolean
37 38 39 40 |
# File 'lib/thin_models/lazy_array.rb', line 37 def empty? each {return false} return true end |
#first ⇒ Object
105 106 107 |
# File 'lib/thin_models/lazy_array.rb', line 105 def first self[0] end |
#inspect ⇒ Object
24 25 26 |
# File 'lib/thin_models/lazy_array.rb', line 24 def inspect "[ThinModels::LazyArray:...]" end |
#join(separator = $,) ⇒ Object
42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/thin_models/lazy_array.rb', line 42 def join(separator=$,) result = ''; first = true each do |x| if first first = false else result << separator if separator end result << x.to_s end result end |
#last ⇒ Object
109 110 111 112 |
# File 'lib/thin_models/lazy_array.rb', line 109 def last l = length self[l-1] if l > 0 end |
#length ⇒ Object
We recommend overriding this #length implementation (which is based on #each) with an efficient implementation. #size will use your #length, and #count uses #size where available, hence will use it too.
31 32 33 |
# File 'lib/thin_models/lazy_array.rb', line 31 def length length = 0; each {length += 1}; length end |
#map(memoize = false, &b) ⇒ Object
map works lazily, resulting in a ThinModels::LazyArray::Mapped or a ThinModels::LazyArray::Memoized::Mapped (which additionally memoizes the mapped values)
116 117 118 |
# File 'lib/thin_models/lazy_array.rb', line 116 def map(memoize=false, &b) (memoize ? Memoized::Mapped : Mapped).new(self, &b) end |
#size ⇒ Object
35 |
# File 'lib/thin_models/lazy_array.rb', line 35 def size; length; end |
#slice_from_start_and_length(start, length) ⇒ Object
We recommend overriding this inefficient implementation (which uses #each to traverse from the start until it reaches the desired range) with an efficient implementation.
Returns an array for the requested slice; may return a slice shorter than requested where the array doesn’t extend that far, but if the start index is greater than the total length, must return nil. This is consistent with Array#slice/[] eg: [][1..10] == nil, but [][0..10] == []
Does not need to handle the other argument types (Range, single index) which Array#slice/[] takes.
71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/thin_models/lazy_array.rb', line 71 def slice_from_start_and_length(start, length) result = [] stop = start + length index = 0 each do |item| break if index >= stop result << item if index >= start index += 1 end result if index >= start end |
#to_json(*p) ⇒ Object
58 59 60 |
# File 'lib/thin_models/lazy_array.rb', line 58 def to_json(*p) to_a.to_json(*p) end |