b-lazy 0.0.4 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/b-lazy.rb +88 -20
  2. metadata +2 -2
data/lib/b-lazy.rb CHANGED
@@ -5,6 +5,8 @@
5
5
  # few convenient methods that can simplify looping constructs.
6
6
  class Enumerator
7
7
 
8
+ # If the Enumerator is empty, then return false. Otherwise,
9
+ # return true.
8
10
  def has_next?
9
11
  peek
10
12
  true
@@ -12,6 +14,9 @@ class Enumerator
12
14
  false
13
15
  end
14
16
 
17
+
18
+ # If the Enumerator is empty, then return true. Otherwise,
19
+ # return false.
15
20
  def empty?
16
21
  peek
17
22
  false
@@ -20,6 +25,8 @@ class Enumerator
20
25
  end
21
26
 
22
27
 
28
+ # This is similar to the #take method, except that it
29
+ # actually moves the Enumerator ahead n after each call.
23
30
  def grab(n)
24
31
  retval = []
25
32
  begin
@@ -46,10 +53,14 @@ module Enumerable
46
53
  end
47
54
 
48
55
 
49
- # This is similar to the tap method. It allows you
50
- # to examine each item as it passes through the
51
- # Enumeration pipeline. It is also handy if you want
52
- # to modify an element's state as it passes through.
56
+ # This is similar to the tap method, but it operates on
57
+ # each element of the Enumerator as it passes through.
58
+ # This is useful for many things, such as:
59
+ #
60
+ # 1. Examining the state of the element
61
+ # 2. Logging
62
+ # 3. Modifying the element's state
63
+ # 4. Recording interim values
53
64
  def touch(&blk)
54
65
  Enumerator.new do |out|
55
66
  self.each do |x|
@@ -60,6 +71,8 @@ module Enumerable
60
71
  end
61
72
 
62
73
 
74
+ # This is the same as the #select method except that it
75
+ # operates lazily.
63
76
  def lselect(&blk)
64
77
  Enumerator.new do |out|
65
78
  self.each do |i|
@@ -68,6 +81,9 @@ module Enumerable
68
81
  end
69
82
  end
70
83
 
84
+
85
+ # This is the same as the #reject method except that it
86
+ # operates lazily.
71
87
  def lreject(&blk)
72
88
  Enumerator.new do |out|
73
89
  self.each do |i|
@@ -75,12 +91,9 @@ module Enumerable
75
91
  end
76
92
  end
77
93
  end
78
-
79
-
80
94
 
81
95
 
82
-
83
- # Start as soon as the condition becomes true
96
+ # Begins yielding values as soon as the condition becomes true.
84
97
  def start_when(&blk)
85
98
  Enumerator.new do |out|
86
99
  s = self.ensure_enum
@@ -149,6 +162,8 @@ module Enumerable
149
162
  end
150
163
 
151
164
 
165
+ # Skips the specified number of elements. Note that this
166
+ # method does not complain if the Enumerator is empty.
152
167
  def skip(n = 1)
153
168
  Enumerator.new do |out|
154
169
  s = self.ensure_enum
@@ -163,6 +178,12 @@ module Enumerable
163
178
  end
164
179
 
165
180
 
181
+ # In Java-speak, we would say this method operates on
182
+ # Enumerable<Enumerable<?>> . It concatenates the values
183
+ # of each nested Enumerable and produces one Enumerable that
184
+ # contains all of the values. For example:
185
+ #
186
+ # [[1, 2, 3], [4, 5]].cons.to_a -> [1, 2, 3, 4, 5]
166
187
  def cons()
167
188
  Enumerator.new do |out|
168
189
  s = self.ensure_enum
@@ -176,12 +197,11 @@ module Enumerable
176
197
  end
177
198
 
178
199
 
179
- # NOTE: This method should only be called on Enumerators
180
- # of Enumerators! This is similar to cons, but it
181
- # instead takes the first item from each enumerator,
182
- # then the second item, etc. This can be handy when
183
- # you have a finite number of enumerators, but each
184
- # one may hold an infinite number of items
200
+ # This is similar to cons, but it
201
+ # instead takes the first item from each enumerator,
202
+ # then the second item, etc. This can be handy when
203
+ # you have a finite number of enumerators, but each
204
+ # one may hold an infinite number of items
185
205
  def weave()
186
206
  Enumerator.new do |out|
187
207
  enums = self.ensure_enum.lmap(&:ensure_enum)
@@ -195,6 +215,10 @@ module Enumerable
195
215
  end
196
216
 
197
217
 
218
+ # If you have an infinite number of Enumerators, and each of these
219
+ # have an infinite number of elements, then you should iterate over
220
+ # them using Cantor's diagonalization technique. As t -> infinity,
221
+ # you will examine all elements from all Enumerators.
198
222
  def diagonalize()
199
223
  Enumerator.new do |out|
200
224
  s = self.ensure_enum
@@ -210,7 +234,27 @@ module Enumerable
210
234
  end
211
235
 
212
236
 
213
-
237
+ # Randomizes the order in which the elements are yielded. Since
238
+ # this is done in a lazy fashion, it is not as random as actually
239
+ # shuffling the entire list.
240
+ def randomly(n = 8)
241
+ Enumerator.new do |out|
242
+ s = self.ensure_enum
243
+ pool = s.grab(n)
244
+ while s.has_next?
245
+ index = rand(n)
246
+ out.yield pool[index]
247
+ pool[index] = s.next
248
+ end
249
+ pool.sort_by{rand}.each{|x| out.yield x}
250
+ end
251
+ end
252
+
253
+
254
+ # This is similar to Array's transpose method, but it can operate
255
+ # on any Enumerable. Additionally, it stops as soon as the first
256
+ # Enumerable is exhausted (rather than setting the missing values
257
+ # equal to nil).
214
258
  def ltranspose()
215
259
  Enumerator.new do |out|
216
260
  catch(:nothing_to_do) do
@@ -227,15 +271,39 @@ module Enumerable
227
271
  end
228
272
 
229
273
 
230
- def groups_of(n)
274
+
275
+ # Keeps repeating the same elements indefinitely.
276
+ def cycle()
231
277
  Enumerator.new do |out|
232
- s = self.ensure_enum
233
- while s.has_next?
234
- out.yield s.grab(n)
278
+ values = self.touch{|x| out.yield x}.to_a
279
+ unless values.empty?
280
+ loop do
281
+ values.each{|x| out.yield x}
282
+ end
283
+ end
284
+ end
285
+ end
286
+
287
+
288
+ # This is a lazy version of the #product method. It returns
289
+ # all combinations of values from the provided Enumerators.
290
+ #
291
+ # Ex: [[1, 2], [3, 4]].lproduct.to_a -> [[1, 3], [1, 4], [2, 3], [2, 4]]
292
+ #def lproduct()
293
+ #
294
+ #end
295
+
296
+
297
+ # Repeats the same sequence of elements n times.
298
+ def repeat(n)
299
+ n = n.to_i
300
+ Enumerator.new do |out|
301
+ if n >= 1
302
+ values = self.touch{|x| out.yield x}.to_a
303
+ (n - 1).times{ values.each{|x| out.yield x} }
235
304
  end
236
305
  end
237
306
  end
238
-
239
307
 
240
308
 
241
309
  # When #to_enum is called on an Enumerator, it creates a copy
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
+ - 1
7
8
  - 0
8
- - 4
9
- version: 0.0.4
9
+ version: 0.1.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Brian Lauber