Class: Enumerator::Lazy

Inherits:
Enumerator show all
Defined in:
lib/backports/2.0.0/enumerable/lazy.rb

Constant Summary collapse

@@done =

used internally to bail out of an iteration

:__backports_lazy_enumeration_done__
@@lazy_with_no_block =

used internally to create lazy without block

Struct.new(:object, :method, :args)

Instance Method Summary collapse

Methods inherited from Enumerator

#initialize_with_optional_block, produce, product

Constructor Details

#initialize(obj) ⇒ Lazy

Returns a new instance of Lazy.

Raises:

  • (ArgumentError)


26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/backports/2.0.0/enumerable/lazy.rb', line 26

def initialize(obj)
  if obj.is_a?(@@lazy_with_no_block)
    @inspect_info = obj
    return super(@receiver = obj.object, @method = obj.method || :each, * @args = obj.args)
  end
  raise ArgumentError, "must supply a block" unless block_given?
  @receiver = obj
  super() do |yielder, *args|
    catch @@done do
      obj.each(*args) do |*x|
        yield yielder, *x
      end
    end
  end
end

Instance Method Details

#chunkObject



80
81
82
# File 'lib/backports/2.0.0/enumerable/lazy.rb', line 80

def chunk(*)
  super.lazy
end

#drop(n) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
# File 'lib/backports/2.0.0/enumerable/lazy.rb', line 124

def drop(n)
  n = Backports::coerce_to_int(n)
  Lazy.new(self) do |yielder, *values|
    data = yielder.backports_memo ||= {:remain => n}
    if data[:remain] > 0
      data[:remain] -= 1
    else
      yielder.yield(*values)
    end
  end.__set_inspect :drop, [n]
end

#drop_whileObject

Raises:

  • (ArgumentError)


136
137
138
139
140
141
142
# File 'lib/backports/2.0.0/enumerable/lazy.rb', line 136

def drop_while
  raise ArgumentError, "tried to call lazy drop_while without a block" unless block_given?
  Lazy.new(self) do |yielder, *values|
    data = yielder.backports_memo ||= {:dropping => true}
    yielder.yield(*values) unless data[:dropping] &&= yield(*values)
  end.__set_inspect :drop_while
end

#flat_mapObject Also known as: collect_concat

Raises:

  • (ArgumentError)


162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/backports/2.0.0/enumerable/lazy.rb', line 162

def flat_map
  raise ArgumentError, "tried to call lazy flat_map without a block" unless block_given?
  Lazy.new(self) do |yielder, *values|
    result = yield(*values)
    ary = Backports.is_array?(result)
    if ary || (result.respond_to?(:each) && result.respond_to?(:force))
      (ary || result).each{|x| yielder << x }
    else
      yielder << result
    end
  end.__set_inspect :flat_map
end

#grep(pattern) ⇒ Object



109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/backports/2.0.0/enumerable/lazy.rb', line 109

def grep(pattern)
  if block_given?
    # Split for performance
    Lazy.new(self) do |yielder, *values|
      values = values.first unless values.size > 1
      yielder.yield(yield(values)) if pattern === values
    end
  else
    Lazy.new(self) do |yielder, *values|
      values = values.first unless values.size > 1
      yielder.yield(values) if pattern === values
    end
  end.__set_inspect :grep, [pattern]
end

#inspectObject



53
54
55
56
57
58
# File 'lib/backports/2.0.0/enumerable/lazy.rb', line 53

def inspect
  suff = ''
  suff << ":#{@method}" unless @method.nil? || @method == :each
  suff << "(#{@args.inspect[1...-1]})" if @args && !@args.empty?
  "#<#{self.class}: #{@receiver.inspect}#{suff}>"
end

#lazyObject



44
45
46
# File 'lib/backports/2.0.0/enumerable/lazy.rb', line 44

def lazy
  self
end

#mapObject Also known as: collect

Raises:

  • (ArgumentError)


84
85
86
87
88
89
# File 'lib/backports/2.0.0/enumerable/lazy.rb', line 84

def map
  raise ArgumentError, "tried to call lazy map without a block" unless block_given?
  Lazy.new(self) do |yielder, *values|
    yielder << yield(*values)
  end.__set_inspect :map
end

#rejectObject

Raises:

  • (ArgumentError)


101
102
103
104
105
106
107
# File 'lib/backports/2.0.0/enumerable/lazy.rb', line 101

def reject
  raise ArgumentError, "tried to call lazy reject without a block" unless block_given?
  Lazy.new(self) do |yielder, *values|
    values = values.first unless values.size > 1
    yielder.yield(values) unless yield values
  end.__set_inspect :reject
end

#selectObject Also known as: find_all

Raises:

  • (ArgumentError)


92
93
94
95
96
97
98
# File 'lib/backports/2.0.0/enumerable/lazy.rb', line 92

def select
  raise ArgumentError, "tried to call lazy select without a block" unless block_given?
  Lazy.new(self) do |yielder, *values|
    values = values.first unless values.size > 1
    yielder.yield values if yield values
  end.__set_inspect :select
end

#take(n) ⇒ Object

Raises:

  • (ArgumentError)


144
145
146
147
148
149
150
151
152
# File 'lib/backports/2.0.0/enumerable/lazy.rb', line 144

def take(n)
  n = Backports::coerce_to_int(n)
  raise ArgumentError, 'attempt to take negative size' if n < 0
  Lazy.new(n == 0 ? [] : self) do |yielder, *values|
    data = yielder.backports_memo ||= {:remain => n}
    yielder.yield(*values)
    throw @@done if (data[:remain] -= 1) == 0
  end.__set_inspect :take, [n], self
end

#take_whileObject

Raises:

  • (ArgumentError)


154
155
156
157
158
159
160
# File 'lib/backports/2.0.0/enumerable/lazy.rb', line 154

def take_while
  raise ArgumentError, "tried to call lazy take_while without a block" unless block_given?
  Lazy.new(self) do |yielder, *values|
    throw @@done unless yield(*values)
    yielder.yield(*values)
  end.__set_inspect :take_while
end

#to_enum(method = :each, *args) ⇒ Object Also known as: enum_for



48
49
50
# File 'lib/backports/2.0.0/enumerable/lazy.rb', line 48

def to_enum(method = :each, *args)
  Lazy.new(@@lazy_with_no_block.new(self, method, args))
end

#zip(*args) ⇒ Object



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/backports/2.0.0/enumerable/lazy.rb', line 176

def zip(*args)
  return super if block_given?
  arys = args.map{ |arg| Backports.is_array?(arg) }
  if arys.all?
    # Handle trivial case of multiple array arguments separately
    # by avoiding Enumerator#next for efficiency & compatibility
    Lazy.new(self) do |yielder, *values|
      data = yielder.backports_memo ||= {:iter => 0}
      values = values.first unless values.size > 1
      yielder << arys.map{|ary| ary[data[:iter]]}.unshift(values)
      data[:iter] += 1
    end
  else
    args.each do |a|
      raise TypeError, "wrong argument type #{a.class} (must respond to :each)" unless a.respond_to? :each
    end
    Lazy.new(self) do |yielder, *values|
      enums = yielder.backports_memo ||= args.map(&:to_enum)
      values = values.first unless values.size > 1
      others = enums.map do |arg|
        begin
          arg.next
        rescue StopIteration
          nil
        end
      end
      yielder << others.unshift(values)
    end
  end.__set_inspect :zip, args
end