Module: DeferredEnumerable

Includes:
Enumerable
Included in:
DeferredEnumerator
Defined in:
lib/deferred_enumerable.rb

Instance Method Summary collapse

Methods included from Enumerable

#defer

Instance Method Details

#all?(&blk) ⇒ Boolean

Passes each element of the collection to the given block. The method returns true if the block never returns false or nil.

Returns:

  • (Boolean)


6
7
8
9
10
# File 'lib/deferred_enumerable.rb', line 6

def all?(&blk) # :yields: obj
  blk ||= proc { |e| e }
  each { |entry| return false unless blk.call(entry) }
  true
end

#any?(&blk) ⇒ Boolean

Passes each element of the collection to the given block. The method returns true if the block ever returns a value other than false or nil.

Returns:

  • (Boolean)


14
15
16
17
18
# File 'lib/deferred_enumerable.rb', line 14

def any?(&blk) # :yields: obj
  blk ||= proc { |e| e }
  each { |entry| return true if blk.call(entry) }
  false
end

#collect(&block) ⇒ Object Also known as: map

Returns a new enumerator with the results of running block once for every element in enum.



30
31
32
33
34
# File 'lib/deferred_enumerable.rb', line 30

def collect(&block) # :yields: obj
  return self unless block_given?

  DeferredEnumerator::Map.new(self, block)
end

#compactObject

Returns a enumerator with all nil elements removed.



223
224
225
# File 'lib/deferred_enumerable.rb', line 223

def compact
  reject(&:nil?)
end

#concat(*enumerables) ⇒ Object Also known as: chain, +

Appends the enumerables to self.

Raises:

  • (TypeError)


228
229
230
231
232
233
234
235
236
# File 'lib/deferred_enumerable.rb', line 228

def concat(*enumerables)
  raise TypeError, 'DeferredEnumerabler#concat accepts only enumerables' unless enumerables.all? { |e| e.is_a?(Enumerable) }

  DeferredEnumerator.new do |yielder|
    [self, *enumerables].each do |enum|
      enum.each { |entry| yielder << entry }
    end
  end
end

#cycle(n = nil) ⇒ Object

Calls block for each element of enum repeatedly n times or forever if none or nil is given. If a non-positive number is given or the collection is empty, does nothing. Returns nil if the loop has finished without getting interrupted.

Unlike Enumerable#cycle DeferredEnumerable#cycle DOES NOT save elements in an internal array.

If no block is given, an enumerator is returned instead.



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/deferred_enumerable.rb', line 88

def cycle(n = nil) # :yields: obj
  cycles_num = n.is_a?(Fixnum) ? n : nil

  enum = DeferredEnumerator.new do |yielder|
    while cycles_num.nil? || cycles_num > 0
      each { |entry| yielder << entry }

      cycles_num -= 1 if cycles_num
    end
  end

  unless block_given?
    enum
  else
    enum.each { |e| yield(e) }

    nil
  end
end

#drop(n) ⇒ Object

Drops first n elements from enum, and returns rest elements in an enumerator.

Raises:

  • (TypeError)


109
110
111
112
113
114
115
# File 'lib/deferred_enumerable.rb', line 109

def drop(n)
  raise TypeError, 'Integer (> 0) expected' unless n.is_a?(Fixnum) && n > 0

  DeferredEnumerator.new do |yielder|
    each { |entry| yielder << entry if (n -= 1) < 0}
  end
end

#drop_whileObject

Drops elements up to, but not including, the first element for which the block returns nil or false and returns an enumerator containing the remaining elements.



128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/deferred_enumerable.rb', line 128

def drop_while # :yields: obj
  return self unless block_given?

  DeferredEnumerator.new do |yielder|
    keep = false
    each do |entry|
      keep ||= !yield(entry)

      yielder << entry if keep
    end
  end
end

#flat_map(&blk) ⇒ Object Also known as: collect_concat

Returns a new enumerator with the concatenated results of running block once for every element in enum.



74
75
76
77
78
# File 'lib/deferred_enumerable.rb', line 74

def flat_map(&blk) # :yields: obj
  return flatten unless block_given?

  flatten.collect(&blk)
end

#flatten(level = nil) ⇒ Object

Returns a new enumerator that is a one-dimensional flattening of this enumerator (recursively). That is, for every element that is an Enumerable, extract its elements into the new enumerator. If the optional level argument determines the level of recursion to flatten.



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/deferred_enumerable.rb', line 55

def flatten(level = nil)
  do_recursion, next_level = if level.is_a?(Fixnum)
    [level > 0, level - 1]
  else
    [true, nil]
  end

  DeferredEnumerator.new do |yielder|
    each do |entry|
      if entry.is_a?(Enumerable) && do_recursion
        entry.defer.flatten(next_level).each { |nested| yielder << nested }
      else
        yielder << entry
      end
    end
  end # Enumerator.new
end

#grep(pattern, &blk) ⇒ Object

Returns an array of every element in enum for which Pattern === element. If the optional block is supplied, each matching element is passed to it, and the block’s result is stored in the output array.



158
159
160
161
162
163
164
# File 'lib/deferred_enumerable.rb', line 158

def grep(pattern, &blk) # :yields: obj
  filtered = select { |obj| pattern === obj }

  block_given? ?
      filtered.collect(&blk) :
      filtered
end

#include?(obj) ⇒ Boolean Also known as: member?

Returns true if any member of enum equals obj. Equality is tested using ==.

Returns:

  • (Boolean)


168
169
170
# File 'lib/deferred_enumerable.rb', line 168

def include?(obj) # :yields: obj
  any? { |e| obj == e }
end

#none?(&blk) ⇒ Boolean

Passes each element of the collection to the given block. The method returns true if the block never returns true for all elements. If the block is not given, none? will return true only if none of the collection members is true.

Returns:

  • (Boolean)


23
24
25
26
27
# File 'lib/deferred_enumerable.rb', line 23

def none?(&blk)
  blk ||= proc { |e| e }
  each { |entry| return false if blk.call(entry) }
  true
end

#partitionObject

Returns two enums, the first containing the elements of enum for which the block evaluates to true, the second containing the rest.



174
175
176
# File 'lib/deferred_enumerable.rb', line 174

def partition # :yields: obj
  super.map(&:defer)
end

#push(element) ⇒ Object Also known as: <<

Appends the element to end of enumerator



241
242
243
# File 'lib/deferred_enumerable.rb', line 241

def push(element)
  concat([element])
end

#reject(&block) ⇒ Object

Returns a enumerator containing all elements of enum for which block is false



46
47
48
49
50
# File 'lib/deferred_enumerable.rb', line 46

def reject(&block) # :yields: obj
  return self unless block_given?

  select { |e| !block.call(e) }
end

#select(&block) ⇒ Object Also known as: find_all

Returns a enumerator containing all elements of enum for which block is not false



38
39
40
41
42
# File 'lib/deferred_enumerable.rb', line 38

def select(&block) # :yields: obj
  return self unless block_given?

  DeferredEnumerator::Select.new(self, block)
end

#sortObject

Returns an enumerator containing the items in enum sorted, either according to their own <=> method, or by using the results of the supplied block.



181
182
183
# File 'lib/deferred_enumerable.rb', line 181

def sort
  super.defer
end

#sort_byObject

Sorts enum using a set of keys generated by mapping the values in enum through the given block.



186
187
188
# File 'lib/deferred_enumerable.rb', line 186

def sort_by
  super.defer
end

#take(n) ⇒ Object

Returns first n elements from enum.

Raises:

  • (TypeError)


118
119
120
121
122
123
124
# File 'lib/deferred_enumerable.rb', line 118

def take(n)
  raise TypeError, 'Integer (> 0) expected' unless n.is_a?(Fixnum) && n > 0

  DeferredEnumerator.new do |yielder|
    each { |entry| yielder << entry if (n -= 1) >= 0 }
  end
end

#take_whileObject

Passes elements to the block until the block returns nil or false, then stops iterating and returns an enumerator of all prior elements.



143
144
145
146
147
148
149
150
151
152
153
# File 'lib/deferred_enumerable.rb', line 143

def take_while # :yields: obj
  return self unless block_given?

  DeferredEnumerator.new do |yielder|
    each do |entry|
      break unless yield(entry)

      yielder << entry
    end
  end
end

#uniqObject

Returns a new enumerator by removing duplicate values in self.



247
248
249
250
251
252
253
254
255
256
257
# File 'lib/deferred_enumerable.rb', line 247

def uniq
  values = {}

  select { |entry|
    value = block_given? ? yield(entry) : entry

    unless values.has_key?(value)
      values.store(value, true)
    end
  }
end

#zip(*enumerables) ⇒ Object

Takes one element from enum and merges corresponding elements from each enumerables. This generates a sequence of n-element arrays, where n is one more than the count of arguments. The length of the resulting sequence will be enum#size. If the size of any argument is less than enum#size, nil values are supplied. If a block is given, it is invoked for each output array, otherwise an enumerator of arrays is returned.

Raises:

  • (TypeError)


198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/deferred_enumerable.rb', line 198

def zip(*enumerables)
  return super if block_given?

  raise TypeError, 'Zip accepts only enumerables' unless enumerables.all? { |e| e.is_a?(Enumerable) }

  deferred = enumerables.map(&:defer)

  DeferredEnumerator.new do |yielder|
    each do |entry|
      ary = [entry]

      deferred.each do |enum|
        ary << begin
          enum.next
        rescue StopIteration
          nil
        end
      end

      yielder << ary
    end
  end
end