deferred_enum 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -0
- data/Gemfile +8 -0
- data/LICENSE +20 -0
- data/README.rdoc +34 -0
- data/Rakefile +1 -0
- data/deferred_enum.gemspec +23 -0
- data/lib/deferred_enum.rb +1 -0
- data/lib/deferred_enum/enumerable.rb +5 -0
- data/lib/deferred_enum/version.rb +3 -0
- data/lib/deferred_enumerable.rb +267 -0
- data/lib/deferred_enumerator.rb +6 -0
- data/spec/defer_spec.rb +12 -0
- data/spec/drop_take_spec.rb +15 -0
- data/spec/map_select_spec.rb +51 -0
- data/spec/predicates_spec.rb +24 -0
- data/spec/test_helper.rb +5 -0
- data/spec/zip_spec.rb +10 -0
- metadata +127 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Alexey Mikhaylov
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
== Synopsys
|
2
|
+
Ruby Enumerable extension. Main idea is lazy computations within enumerators.
|
3
|
+
|
4
|
+
== Usage
|
5
|
+
Install as a gem:
|
6
|
+
sudo gem install deferred_enum
|
7
|
+
|
8
|
+
This gem introduces DeferredEnumerator class:
|
9
|
+
ary = [1, 2, 3, 4]
|
10
|
+
deferred = ary.defer # #<DeferredEnumerator: [1, 2, 3, 4]:each>
|
11
|
+
|
12
|
+
DeferredEnumerator brings some optimizations to all?, any? and none? predicates
|
13
|
+
deferred.all?(&:even?) # Will stop iteration after first false-result = 1 iteration
|
14
|
+
deferred.none?(&:even?) # 2 iterations
|
15
|
+
deferred.any?(&:even?) # 2 iterations
|
16
|
+
|
17
|
+
It also introduces lazy versions of Enumerable's #select, #map and #reject methods
|
18
|
+
deferred.map { |i| i + 1 } # #<DeferredEnumerator: #<Enumerator::Generator>:each>
|
19
|
+
deferred.select { |i| i.even? } # #<DeferredEnumerator: #<Enumerator::Generator>:each>
|
20
|
+
deferred.reject { |i| i.odd? } # #<DeferredEnumerator: #<Enumerator::Generator>:each>
|
21
|
+
|
22
|
+
So you can safely chain your filters, they won't be treated as arrays:
|
23
|
+
deferred.map(&:succ).select(&:even?) # #<DeferredEnumerator: #<Enumerator::Generator>:each>
|
24
|
+
|
25
|
+
You can build chains of Enumerables:
|
26
|
+
deferred.concat([2]).to_a # [1, 2, 3, 4, 2]
|
27
|
+
|
28
|
+
Or append elements to the end of enumerator:
|
29
|
+
deferred << 2
|
30
|
+
|
31
|
+
You can even remove duplicates from enumerator, though this operation can be tough:
|
32
|
+
deferred.uniq # #<DeferredEnumerator: #<Enumerator::Generator>:each>
|
33
|
+
|
34
|
+
There are many other methods in DeferredEnumerator, please refer to documentation.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "deferred_enum/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "deferred_enum"
|
7
|
+
s.version = DeferredEnum::VERSION
|
8
|
+
s.authors = ["Alexey Mikhaylov"]
|
9
|
+
s.email = ["amikhailov83@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/take-five/deferred_enum"
|
11
|
+
s.summary = %q{Introduces lazy computations to Enumerable}
|
12
|
+
s.description = File.read(File.expand_path('../README.rdoc', __FILE__))
|
13
|
+
s.date = Time.now.strftime('%Y-%m-%d')
|
14
|
+
|
15
|
+
s.rubyforge_project = "deferred_enum"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
|
22
|
+
s.add_development_dependency "rspec"
|
23
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require "deferred_enumerable"
|
@@ -0,0 +1,267 @@
|
|
1
|
+
module DeferredEnumerable
|
2
|
+
include Enumerable
|
3
|
+
|
4
|
+
# Passes each element of the collection to the given block.
|
5
|
+
# The method returns true if the block never returns false or nil.
|
6
|
+
def all?(&blk) # :yields: obj
|
7
|
+
blk ||= proc { |e| e }
|
8
|
+
each { |entry| return false unless blk.call(entry) }
|
9
|
+
true
|
10
|
+
end
|
11
|
+
|
12
|
+
# Passes each element of the collection to the given block.
|
13
|
+
# The method returns true if the block ever returns a value other than false or nil.
|
14
|
+
def any?(&blk) # :yields: obj
|
15
|
+
blk ||= proc { |e| e }
|
16
|
+
each { |entry| return true if blk.call(entry) }
|
17
|
+
false
|
18
|
+
end
|
19
|
+
|
20
|
+
# Passes each element of the collection to the given block.
|
21
|
+
# The method returns true if the block never returns true for all elements.
|
22
|
+
# If the block is not given, none? will return true only if none of the collection members is true.
|
23
|
+
def none?(&blk)
|
24
|
+
blk ||= proc { |e| e }
|
25
|
+
each { |entry| return false if blk.call(entry) }
|
26
|
+
true
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns a new enumerator with the results of running block once for every element in enum.
|
30
|
+
def collect # :yields: obj
|
31
|
+
return self unless block_given?
|
32
|
+
|
33
|
+
DeferredEnumerator.new do |yielder|
|
34
|
+
each { |entry| yielder << yield(entry) }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
alias map collect
|
38
|
+
|
39
|
+
# Returns a enumerator containing all elements of enum for which block is not false
|
40
|
+
def select # :yields: obj
|
41
|
+
return self unless block_given?
|
42
|
+
|
43
|
+
DeferredEnumerator.new do |yielder|
|
44
|
+
each { |entry| yielder << entry if yield(entry) }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
alias find_all select
|
48
|
+
|
49
|
+
# Returns a enumerator containing all elements of enum for which block is false
|
50
|
+
def reject # :yields: obj
|
51
|
+
return self unless block_given?
|
52
|
+
|
53
|
+
DeferredEnumerator.new do |yielder|
|
54
|
+
each { |entry| yielder << entry unless yield(entry) }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Returns a new enumerator that is a one-dimensional flattening of this enumerator (recursively).
|
59
|
+
# That is, for every element that is an Enumerable, extract its elements into the new enumerator.
|
60
|
+
# If the optional level argument determines the level of recursion to flatten.
|
61
|
+
def flatten(level = nil)
|
62
|
+
do_recursion, next_level = if level.is_a?(Fixnum)
|
63
|
+
[level > 0, level - 1]
|
64
|
+
else
|
65
|
+
[true, nil]
|
66
|
+
end
|
67
|
+
|
68
|
+
DeferredEnumerator.new do |yielder|
|
69
|
+
each do |entry|
|
70
|
+
if entry.is_a?(Enumerable) && do_recursion
|
71
|
+
entry.defer.flatten(next_level).each { |nested| yielder << nested }
|
72
|
+
else
|
73
|
+
yielder << entry
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end # Enumerator.new
|
77
|
+
end # def flatten
|
78
|
+
|
79
|
+
# Returns a new enumerator with the concatenated results of running block once for every element in enum.
|
80
|
+
def flat_map(&blk) # :yields: obj
|
81
|
+
return flatten unless block_given?
|
82
|
+
|
83
|
+
flatten.collect(&blk)
|
84
|
+
end
|
85
|
+
alias collect_concat flat_map
|
86
|
+
|
87
|
+
# Calls block for each element of enum repeatedly n times or forever if none or nil is given.
|
88
|
+
# If a non-positive number is given or the collection is empty, does nothing.
|
89
|
+
# Returns nil if the loop has finished without getting interrupted.
|
90
|
+
#
|
91
|
+
# Unlike <tt>Enumerable#cycle</tt> <tt>DeferredEnumerable#cycle</tt> DOES NOT save elements in an internal array.
|
92
|
+
#
|
93
|
+
# If no block is given, an enumerator is returned instead.
|
94
|
+
def cycle(n = nil) # :yields: obj
|
95
|
+
cycles_num = n.is_a?(Fixnum) ? n : nil
|
96
|
+
|
97
|
+
enum = DeferredEnumerator.new do |yielder|
|
98
|
+
while cycles_num.nil? || cycles_num > 0
|
99
|
+
each { |entry| yielder << entry }
|
100
|
+
|
101
|
+
cycles_num -= 1 if cycles_num
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
unless block_given?
|
106
|
+
enum
|
107
|
+
else
|
108
|
+
enum.each { |e| yield(e) }
|
109
|
+
|
110
|
+
nil
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Drops first n elements from enum, and returns rest elements in an enumerator.
|
115
|
+
def drop(n)
|
116
|
+
raise TypeError, 'Integer (> 0) expected' unless n.is_a?(Fixnum) && n > 0
|
117
|
+
|
118
|
+
DeferredEnumerator.new do |yielder|
|
119
|
+
each { |entry| yielder << entry if (n -= 1) < 0}
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# Returns first n elements from enum.
|
124
|
+
def take(n)
|
125
|
+
raise TypeError, 'Integer (> 0) expected' unless n.is_a?(Fixnum) && n > 0
|
126
|
+
|
127
|
+
DeferredEnumerator.new do |yielder|
|
128
|
+
each { |entry| yielder << entry if (n -= 1) >= 0}
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Drops elements up to, but not including, the first element for which the block returns nil
|
133
|
+
# or false and returns an enumerator containing the remaining elements.
|
134
|
+
def drop_while # :yields: obj
|
135
|
+
return self unless block_given?
|
136
|
+
|
137
|
+
DeferredEnumerator.new do |yielder|
|
138
|
+
keep = false
|
139
|
+
each do |entry|
|
140
|
+
keep ||= !yield(entry)
|
141
|
+
|
142
|
+
yielder << entry if keep
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# Passes elements to the block until the block returns <code>nil</code> or <code>false</code>,
|
148
|
+
# then stops iterating and returns an enumerator of all prior elements.
|
149
|
+
def take_while # :yields: obj
|
150
|
+
return self unless block_given?
|
151
|
+
|
152
|
+
DeferredEnumerator.new do |yielder|
|
153
|
+
each do |entry|
|
154
|
+
break unless yield(entry)
|
155
|
+
|
156
|
+
yielder << entry
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
# Returns an array of every element in enum for which <code>Pattern === element</code>.
|
162
|
+
# If the optional <code>block</code> is supplied, each matching element is passed to it,
|
163
|
+
# and the block's result is stored in the output array.
|
164
|
+
def grep(pattern, &blk) # :yields: obj
|
165
|
+
filtered = select { |obj| pattern === obj }
|
166
|
+
|
167
|
+
block_given? ?
|
168
|
+
filtered.collect(&blk) :
|
169
|
+
filtered
|
170
|
+
end
|
171
|
+
|
172
|
+
# Returns <code>true</code> if any member of <code>enum</code> equals <code>obj</code>.
|
173
|
+
# Equality is tested using <code>==</code>.
|
174
|
+
def include?(obj) # :yields: obj
|
175
|
+
any? { |e| obj == e }
|
176
|
+
end
|
177
|
+
alias member? include?
|
178
|
+
|
179
|
+
# Returns two enums, the first containing the elements of enum for which the block evaluates to true, the second containing the rest.
|
180
|
+
def partition # :yields: obj
|
181
|
+
super.map(&:defer)
|
182
|
+
end
|
183
|
+
|
184
|
+
# Returns an enumerator containing the items in enum sorted,
|
185
|
+
# either according to their own <=> method,
|
186
|
+
# or by using the results of the supplied block.
|
187
|
+
def sort
|
188
|
+
super.defer
|
189
|
+
end
|
190
|
+
|
191
|
+
# Sorts enum using a set of keys generated by mapping the values in enum through the given block.
|
192
|
+
def sort_by
|
193
|
+
super.defer
|
194
|
+
end
|
195
|
+
|
196
|
+
# Takes one element from <i>enum</i> and merges corresponding
|
197
|
+
# elements from each <i>enumerables</i>. This generates a sequence of
|
198
|
+
# <em>n</em>-element arrays, where <em>n</em> is one more than the
|
199
|
+
# count of arguments. The length of the resulting sequence will be
|
200
|
+
# <code>enum#size</code>. If the size of any argument is less than
|
201
|
+
# <code>enum#size</code>, <code>nil</code> values are supplied. If
|
202
|
+
# a block is given, it is invoked for each output array, otherwise
|
203
|
+
# an enumerator of arrays is returned.
|
204
|
+
def zip(*enumerables)
|
205
|
+
return super if block_given?
|
206
|
+
|
207
|
+
raise TypeError, 'Zip accepts only enumerables' unless enumerables.all? { |e| e.is_a?(Enumerable) }
|
208
|
+
|
209
|
+
deferred = enumerables.map(&:defer)
|
210
|
+
|
211
|
+
DeferredEnumerator.new do |yielder|
|
212
|
+
each do |entry|
|
213
|
+
ary = [entry]
|
214
|
+
|
215
|
+
deferred.each do |enum|
|
216
|
+
ary << begin
|
217
|
+
enum.next
|
218
|
+
rescue StopIteration
|
219
|
+
nil
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
yielder << ary
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
# Returns a enumerator with all nil elements removed.
|
229
|
+
def compact
|
230
|
+
reject(&:nil?)
|
231
|
+
end
|
232
|
+
|
233
|
+
# Appends the <code>enumerables</code> to self.
|
234
|
+
def concat(*enumerables)
|
235
|
+
raise TypeError, 'DeferredEnumerabler#concat accepts only enumerables' unless enumerables.all? { |e| e.is_a?(Enumerable) }
|
236
|
+
|
237
|
+
DeferredEnumerator.new do |yielder|
|
238
|
+
[self, *enumerables].each do |enum|
|
239
|
+
enum.each { |entry| yielder << entry }
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
alias chain concat
|
244
|
+
alias + concat
|
245
|
+
|
246
|
+
# Appends the <code>element</code> to end of enumerator
|
247
|
+
def push(element)
|
248
|
+
concat([element])
|
249
|
+
end
|
250
|
+
alias << push
|
251
|
+
|
252
|
+
# Returns a new enumerator by removing duplicate values in self.
|
253
|
+
def uniq
|
254
|
+
values = {}
|
255
|
+
|
256
|
+
select { |entry|
|
257
|
+
value = block_given? ? yield(entry) : entry
|
258
|
+
|
259
|
+
unless values.has_key?(value)
|
260
|
+
values.store(value, true)
|
261
|
+
end
|
262
|
+
}
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
require "deferred_enumerator"
|
267
|
+
require "deferred_enum/enumerable"
|
data/spec/defer_spec.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require File.expand_path('../test_helper', __FILE__)
|
2
|
+
|
3
|
+
describe Enumerable do
|
4
|
+
it "should have defer method" do
|
5
|
+
ary = []
|
6
|
+
ary.should respond_to(:defer)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should return DeferredEnumerable" do
|
10
|
+
[].defer.should be_a(DeferredEnumerable)
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require File.expand_path('../test_helper', __FILE__)
|
2
|
+
|
3
|
+
describe DeferredEnumerator do
|
4
|
+
it "should drop elements from collections" do
|
5
|
+
[1, 2, 3, 4, 3].defer.drop(3).to_a.should == [4, 3]
|
6
|
+
|
7
|
+
[1, 2, 3, 4, 3].defer.drop_while {|n| n <= 3 }.to_a.should == [4, 3]
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should take first elements from collections" do
|
11
|
+
[4, 3, 2, 1, 4].defer.take(3).to_a.should == [4, 3, 2]
|
12
|
+
|
13
|
+
[4, 3, 2, 1, 4].defer.take_while { |n| n > 1 }.to_a.should == [4, 3, 2]
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require File.expand_path('../test_helper', __FILE__)
|
2
|
+
|
3
|
+
describe DeferredEnumerator do
|
4
|
+
it "should map collections" do
|
5
|
+
[1, 2, 3].defer.map { |i| i + 1 }.to_a.should == [2, 3, 4]
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should filter collections" do
|
9
|
+
[1, 2, 3].defer.select { |i| i.odd? }.to_a.should == [1, 3]
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should reject elements from collections" do
|
13
|
+
[1, 2, 3].defer.reject { |i| i.odd? }.to_a.should == [2]
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should flatten collections" do
|
17
|
+
[[1, 2], 3, [4]].defer.flatten.to_a.should == [1, 2, 3, 4]
|
18
|
+
|
19
|
+
[[1, [2]], 3].defer.flatten(1).to_a.should == [1, [2], 3]
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should flat and map collections" do
|
23
|
+
[[1, 2], 3, [4]].defer.flat_map { |i| i + 1 }.to_a.should == [2, 3, 4, 5]
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should cycle collections" do
|
27
|
+
[1].defer.cycle(2).to_a.should == [1, 1]
|
28
|
+
|
29
|
+
counts = 0
|
30
|
+
[1].defer.cycle { counts += 1; break if counts == 10 }
|
31
|
+
counts.should == 10
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should grep collections" do
|
35
|
+
['abc', 'def', 'ghi'].defer.grep(/abc/).to_a.should == ['abc']
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should compact collections" do
|
39
|
+
[1, 2, nil].defer.compact.to_a.should == [1, 2]
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should chain collections" do
|
43
|
+
[1, 2].defer.chain([3], [], [4]).to_a.should == [1, 2, 3, 4]
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should remove duplicates from collections" do
|
47
|
+
[1, 2, 3, 4, 3, 4].defer.uniq.to_a.should == [1, 2, 3, 4]
|
48
|
+
|
49
|
+
[1, 2, 3, 4].defer.uniq { |n| n.even? }.to_a.should == [1, 2]
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.expand_path('../test_helper', __FILE__)
|
2
|
+
|
3
|
+
describe DeferredEnumerator do
|
4
|
+
it "should lazily execute all? method" do
|
5
|
+
counts = 0
|
6
|
+
|
7
|
+
[2, 3, 4].all? { |e| counts += 1; e.even? }.should == false
|
8
|
+
counts.should == 2
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should lazily execute any? method" do
|
12
|
+
counts = 0
|
13
|
+
|
14
|
+
[2, 3, 4].any? { |e| counts += 1; e.odd? }.should == true
|
15
|
+
counts.should == 2
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should lazily execute none? method" do
|
19
|
+
counts = 0
|
20
|
+
|
21
|
+
[2, 3, 4].none? { |e| counts += 1; e.odd? }.should == false
|
22
|
+
counts.should == 2
|
23
|
+
end
|
24
|
+
end
|
data/spec/test_helper.rb
ADDED
data/spec/zip_spec.rb
ADDED
metadata
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: deferred_enum
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Alexey Mikhaylov
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-12-11 00:00:00 +06:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rspec
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
version: "0"
|
31
|
+
type: :development
|
32
|
+
version_requirements: *id001
|
33
|
+
description: |-
|
34
|
+
== Synopsys
|
35
|
+
Ruby Enumerable extension. Main idea is lazy computations within enumerators.
|
36
|
+
|
37
|
+
== Usage
|
38
|
+
Install as a gem:
|
39
|
+
sudo gem install deferred_enum
|
40
|
+
|
41
|
+
This gem introduces DeferredEnumerator class:
|
42
|
+
ary = [1, 2, 3, 4]
|
43
|
+
deferred = ary.defer # #<DeferredEnumerator: [1, 2, 3, 4]:each>
|
44
|
+
|
45
|
+
DeferredEnumerator brings some optimizations to all?, any? and none? predicates
|
46
|
+
deferred.all?(&:even?) # Will stop iteration after first false-result = 1 iteration
|
47
|
+
deferred.none?(&:even?) # 2 iterations
|
48
|
+
deferred.any?(&:even?) # 2 iterations
|
49
|
+
|
50
|
+
It also introduces lazy versions of Enumerable's #select, #map and #reject methods
|
51
|
+
deferred.map { |i| i + 1 } # #<DeferredEnumerator: #<Enumerator::Generator>:each>
|
52
|
+
deferred.select { |i| i.even? } # #<DeferredEnumerator: #<Enumerator::Generator>:each>
|
53
|
+
deferred.reject { |i| i.odd? } # #<DeferredEnumerator: #<Enumerator::Generator>:each>
|
54
|
+
|
55
|
+
So you can safely chain your filters, they won't be treated as arrays:
|
56
|
+
deferred.map(&:succ).select(&:even?) # #<DeferredEnumerator: #<Enumerator::Generator>:each>
|
57
|
+
|
58
|
+
You can build chains of Enumerables:
|
59
|
+
deferred.concat([2]).to_a # [1, 2, 3, 4, 2]
|
60
|
+
|
61
|
+
Or append elements to the end of enumerator:
|
62
|
+
deferred << 2
|
63
|
+
|
64
|
+
You can even remove duplicates from enumerator, though this operation can be tough:
|
65
|
+
deferred.uniq # #<DeferredEnumerator: #<Enumerator::Generator>:each>
|
66
|
+
|
67
|
+
There are many other methods in DeferredEnumerator, please refer to documentation.
|
68
|
+
email:
|
69
|
+
- amikhailov83@gmail.com
|
70
|
+
executables: []
|
71
|
+
|
72
|
+
extensions: []
|
73
|
+
|
74
|
+
extra_rdoc_files: []
|
75
|
+
|
76
|
+
files:
|
77
|
+
- .gitignore
|
78
|
+
- Gemfile
|
79
|
+
- LICENSE
|
80
|
+
- README.rdoc
|
81
|
+
- Rakefile
|
82
|
+
- deferred_enum.gemspec
|
83
|
+
- lib/deferred_enum.rb
|
84
|
+
- lib/deferred_enum/enumerable.rb
|
85
|
+
- lib/deferred_enum/version.rb
|
86
|
+
- lib/deferred_enumerable.rb
|
87
|
+
- lib/deferred_enumerator.rb
|
88
|
+
- spec/defer_spec.rb
|
89
|
+
- spec/drop_take_spec.rb
|
90
|
+
- spec/map_select_spec.rb
|
91
|
+
- spec/predicates_spec.rb
|
92
|
+
- spec/test_helper.rb
|
93
|
+
- spec/zip_spec.rb
|
94
|
+
has_rdoc: true
|
95
|
+
homepage: https://github.com/take-five/deferred_enum
|
96
|
+
licenses: []
|
97
|
+
|
98
|
+
post_install_message:
|
99
|
+
rdoc_options: []
|
100
|
+
|
101
|
+
require_paths:
|
102
|
+
- lib
|
103
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
104
|
+
none: false
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
segments:
|
109
|
+
- 0
|
110
|
+
version: "0"
|
111
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
|
+
none: false
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
segments:
|
117
|
+
- 0
|
118
|
+
version: "0"
|
119
|
+
requirements: []
|
120
|
+
|
121
|
+
rubyforge_project: deferred_enum
|
122
|
+
rubygems_version: 1.3.7
|
123
|
+
signing_key:
|
124
|
+
specification_version: 3
|
125
|
+
summary: Introduces lazy computations to Enumerable
|
126
|
+
test_files: []
|
127
|
+
|