b-lazy 0.0.4 → 0.1.0

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.
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