stream 0.5.2 → 0.5.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3374a923bc2d44c39ea1c1957d5982b26f55a22ac958cfa119be87a978e17676
4
- data.tar.gz: 88b9b768b08a6edf3a689f76f50627784825b15ac1ed07d6b3172bb34ce69fa3
3
+ metadata.gz: cbfc5988a8fe8b8e4735b9f576da07e6e1aa18a87b4b8a6df0c917b5a9789a13
4
+ data.tar.gz: 06d3fe1334d5adbce1123621410c22efab33159396e967eb96d18d926c8c9080
5
5
  SHA512:
6
- metadata.gz: fd0f115fefc0969ccde444c8200d9f279b8d9736af6c91884d89e5fa9dd4a46dccb6b570da4467b7dfaa35e038644b09dbf25348289a66cf0ea919c4c21c732b
7
- data.tar.gz: 56d49b892e3355026bb05bd98535471ebfe9e8564f9f1885e43938deda8b7f3e33551fcd15f1b492821944de5707ef296dff3f134812b1f8e904ce0ef8b4f037
6
+ metadata.gz: 161659d0943d54ca3c0ab0eadddf9933f800d57108b0f3f1368929fdc01bebb3dbb0cf12bc1cff8b82cffb005b7a1e04d2646a1ea628b692dd6890afa576310c
7
+ data.tar.gz: 55f2c790ea82ef64f90bdef541303ec4a2fc6be1292a19a96648f5bfc1159cd17e807d1264d1d98c55a6b5298129037c5576cd7b94f22931686cdd57e1e08f4f
data/Gemfile CHANGED
@@ -1,5 +1,3 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
-
5
- gem "codeclimate-test-reporter", group: :test, require: nil
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- stream (0.5.2)
4
+ stream (0.5.3)
5
+ generator
5
6
 
6
7
  GEM
7
8
  remote: https://rubygems.org/
@@ -9,6 +10,7 @@ GEM
9
10
  codeclimate-test-reporter (1.0.9)
10
11
  simplecov (<= 0.13)
11
12
  docile (1.1.5)
13
+ generator (0.0.1)
12
14
  json (2.1.0)
13
15
  power_assert (1.1.3)
14
16
  rake (12.3.2)
@@ -24,6 +26,7 @@ GEM
24
26
 
25
27
  PLATFORMS
26
28
  ruby
29
+ x86_64-linux
27
30
 
28
31
  DEPENDENCIES
29
32
  codeclimate-test-reporter
@@ -34,4 +37,4 @@ DEPENDENCIES
34
37
  yard
35
38
 
36
39
  BUNDLED WITH
37
- 2.0.1
40
+ 2.2.1
data/LICENSE ADDED
@@ -0,0 +1,56 @@
1
+ Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.jp>.
2
+ You can redistribute it and/or modify it under either the terms of the
3
+ 2-clause BSDL (see the file BSDL), or the conditions below:
4
+
5
+ 1. You may make and give away verbatim copies of the source form of the
6
+ software without restriction, provided that you duplicate all of the
7
+ original copyright notices and associated disclaimers.
8
+
9
+ 2. You may modify your copy of the software in any way, provided that
10
+ you do at least ONE of the following:
11
+
12
+ a) place your modifications in the Public Domain or otherwise
13
+ make them Freely Available, such as by posting said
14
+ modifications to Usenet or an equivalent medium, or by allowing
15
+ the author to include your modifications in the software.
16
+
17
+ b) use the modified software only within your corporation or
18
+ organization.
19
+
20
+ c) give non-standard binaries non-standard names, with
21
+ instructions on where to get the original software distribution.
22
+
23
+ d) make other distribution arrangements with the author.
24
+
25
+ 3. You may distribute the software in object code or binary form,
26
+ provided that you do at least ONE of the following:
27
+
28
+ a) distribute the binaries and library files of the software,
29
+ together with instructions (in the manual page or equivalent)
30
+ on where to get the original distribution.
31
+
32
+ b) accompany the distribution with the machine-readable source of
33
+ the software.
34
+
35
+ c) give non-standard binaries non-standard names, with
36
+ instructions on where to get the original software distribution.
37
+
38
+ d) make other distribution arrangements with the author.
39
+
40
+ 4. You may modify and include the part of the software into any other
41
+ software (possibly commercial). But some files in the distribution
42
+ are not written by the author, so that they are not under these terms.
43
+
44
+ For the list of those files and their copying conditions, see the
45
+ file LEGAL.
46
+
47
+ 5. The scripts and library files supplied as input to or produced as
48
+ output from the software do not automatically fall under the
49
+ copyright of the software, but belong to whomever generated them,
50
+ and may be sold commercially, and may be aggregated with this
51
+ software.
52
+
53
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
54
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
55
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56
+ PURPOSE.
@@ -168,5 +168,5 @@ root privileges to install.
168
168
  == Other Stuff
169
169
 
170
170
  Author:: Horst Duchene
171
- License:: Copyright (c) 2001, 2013, 2016 Horst Duchene
171
+ License:: Copyright (c) 2001, 2013, 2016, 2020 Horst Duchene
172
172
  Released under the same license as Ruby
data/Rakefile CHANGED
@@ -21,8 +21,8 @@ task :default => :test
21
21
  # Define a test task.
22
22
 
23
23
  Rake::TestTask.new do |t|
24
- t.libs << "tests"
25
- t.pattern = 'tests/Test*.rb'
24
+ t.libs << 'test'
25
+ t.pattern = 'test/test*.rb'
26
26
  t.verbose = true
27
27
  end
28
28
 
@@ -1,4 +1,4 @@
1
- STREAM_VERSION = "0.5.2"
1
+ STREAM_VERSION = '0.5.3'.freeze
2
2
 
3
3
  ##
4
4
  # Module Stream defines an interface for an external Iterator which
@@ -14,15 +14,20 @@ module Stream
14
14
  class EndOfStreamException < StandardError; end
15
15
 
16
16
  # Returns false if the next #forward will return an element.
17
- def at_end?; raise NotImplementedError; end
17
+ def at_end?
18
+ raise NotImplementedError
19
+ end
18
20
 
19
21
  # Returns false if the next #backward will return an element.
20
- def at_beginning?; raise NotImplementedError; end
22
+ def at_beginning?
23
+ raise NotImplementedError
24
+ end
21
25
 
22
26
  # Move forward one position. Returns the _target_ of current_edge.
23
27
  # Raises Stream::EndOfStreamException if at_end? is true.
24
28
  def forward
25
29
  raise EndOfStreamException if at_end?
30
+
26
31
  basic_forward
27
32
  end
28
33
 
@@ -30,28 +35,41 @@ module Stream
30
35
  # Stream::EndOfStreamException if at_beginning? is true.
31
36
  def backward
32
37
  raise EndOfStreamException if at_beginning?
38
+
33
39
  basic_backward
34
40
  end
35
41
 
36
42
  # Position the stream before its first element, i.e. the next #forward
37
43
  # will return the first element.
38
44
  def set_to_begin
39
- until at_beginning?; basic_backward; end
45
+ basic_backward until at_beginning?
40
46
  end
41
47
 
42
48
  # Position the stream behind its last element, i.e. the next #backward
43
49
  # will return the last element.
44
50
  def set_to_end
45
- until at_end?; basic_forward; end
51
+ basic_forward until at_end?
46
52
  end
47
53
 
48
54
  protected
49
55
 
50
- def basic_forward; raise NotImplementedError; end
51
- def basic_backward; raise NotImplementedError; end
56
+ def basic_forward
57
+ raise NotImplementedError
58
+ end
59
+
60
+ def basic_backward
61
+ raise NotImplementedError
62
+ end
52
63
 
53
- def basic_current; backward; forward; end
54
- def basic_peek; forward; backward; end
64
+ def basic_current
65
+ backward
66
+ forward
67
+ end
68
+
69
+ def basic_peek
70
+ forward
71
+ backward
72
+ end
55
73
 
56
74
  public
57
75
 
@@ -62,77 +80,106 @@ module Stream
62
80
  # current position. #detect, which is inherited from Enumerable uses
63
81
  # #each, which implicitly calls #set_to_begin.
64
82
  def move_forward_until
65
- until at_end?
66
- element = basic_forward
67
- return element if yield(element)
68
- end
69
- nil
83
+ until at_end?
84
+ element = basic_forward
85
+ return element if yield(element)
86
+ end
87
+ nil
70
88
  end
71
89
 
72
90
  # Move backward until the boolean block is not false and returns the element
73
91
  # found. Returns nil if no object matches.
74
92
  def move_backward_until
75
- until at_beginning?
76
- element = basic_backward
77
- return element if yield(element)
78
- end
79
- nil
93
+ until at_beginning?
94
+ element = basic_backward
95
+ return element if yield(element)
96
+ end
97
+ nil
80
98
  end
81
99
 
82
100
  # Returns the element returned by the last call of #forward. If at_beginning?
83
101
  # is true self is returned.
84
- def current; at_beginning? ? self : basic_current; end
102
+ def current
103
+ at_beginning? ? self : basic_current
104
+ end
85
105
 
86
106
  # Returns the element returned by the last call of #backward. If at_end? is
87
107
  # true self is returned.
88
- def peek; at_end? ? self : basic_peek; end
108
+ def peek
109
+ at_end? ? self : basic_peek
110
+ end
89
111
 
90
112
  # Returns the array [#current,#peek].
91
- def current_edge; [current,peek]; end
113
+ def current_edge
114
+ [current, peek]
115
+ end
92
116
 
93
117
  # Returns the first element of the stream. This is accomplished by calling
94
118
  # set_to_begin and #forward, which means a state change.
95
- def first; set_to_begin; forward; end
119
+ def first
120
+ set_to_begin
121
+ forward
122
+ end
96
123
 
97
124
  # Returns the last element of the stream. This is accomplished by calling
98
125
  # set_to_begin and #backward, which means a state change.
99
- def last; set_to_end; backward; end
126
+ def last
127
+ set_to_end
128
+ backward
129
+ end
100
130
 
101
131
  # Returns true if the stream is empty which is equivalent to at_end? and
102
132
  # at_beginning? both being true.
103
- def empty?; at_end? and at_beginning?; end
133
+ def empty?
134
+ at_end? and at_beginning?
135
+ end
104
136
 
105
137
  # Implements the standard iterator used by module Enumerable, by calling
106
138
  # set_to_begin and basic_forward until at_end? is true.
107
139
  def each
108
140
  set_to_begin
109
- until at_end?
110
- yield basic_forward
111
- end
141
+ yield basic_forward until at_end?
112
142
  end
113
143
 
114
144
  # create_stream is used for each Enumerable to create a stream for it. A
115
145
  # Stream as an Enumerable returns itself.
116
- def create_stream; self end
146
+ def create_stream
147
+ self
148
+ end
117
149
 
118
150
  # A Stream::WrappedStream should return the wrapped stream unwrapped. If the
119
151
  # stream is not a wrapper around another stream it simply returns itself.
120
- def unwrapped; self; end
152
+ def unwrapped
153
+ self
154
+ end
121
155
 
122
156
  # The abstract super class of all concrete Classes implementing the Stream
123
157
  # interface. Only used for including module Stream.
124
158
  class BasicStream
125
- include Stream
159
+ include Stream
126
160
  end
127
161
 
128
162
  # A Singleton class for an empty stream. EmptyStream.instance is the sole
129
163
  # instance which answers true for both at_end? and at_beginning?
130
164
  class EmptyStream < BasicStream
131
- require 'singleton'
132
- include Singleton
165
+ require 'singleton'
166
+ include Singleton
167
+
168
+ def at_end?
169
+ true
170
+ end
171
+
172
+ def at_beginning?
173
+ true
174
+ end
133
175
 
134
- def at_end?; true; end
135
- def at_beginning?; true; end
176
+ def basic_forward
177
+ raise EndOfStreamException
178
+ end
179
+
180
+ def basic_backward
181
+ raise EndOfStreamException
182
+ end
136
183
  end
137
184
 
138
185
  # A CollectionStream can be used as an external iterator for each
@@ -142,34 +189,56 @@ module Stream
142
189
  # A CollectionStream for an array is created by the method
143
190
  # Array#create_stream.
144
191
  class CollectionStream < BasicStream
145
- attr_reader :pos
192
+ attr_reader :pos
146
193
 
147
- # Creates a new CollectionStream for the indexable sequence _seq_.
148
- def initialize(seq)
149
- @seq = seq
150
- set_to_begin
151
- end
194
+ # Creates a new CollectionStream for the indexable sequence _seq_.
195
+ def initialize(seq)
196
+ @seq = seq
197
+ set_to_begin
198
+ end
152
199
 
153
- def at_end?; @pos + 1 >= @seq.size; end
154
- def at_beginning?; @pos < 0; end
200
+ def at_end?
201
+ @pos + 1 >= @seq.size
202
+ end
155
203
 
156
- # positioning
204
+ def at_beginning?
205
+ @pos < 0
206
+ end
157
207
 
158
- #
159
- def set_to_begin; @pos = -1; end
160
- def set_to_end; @pos = @seq.size - 1; end
208
+ # positioning
161
209
 
162
- def basic_forward; @pos += 1; @seq[@pos]; end
163
- def basic_backward; r = @seq[@pos]; @pos -= 1; r; end
210
+ def set_to_begin
211
+ @pos = -1
212
+ end
213
+
214
+ def set_to_end
215
+ @pos = @seq.size - 1
216
+ end
217
+
218
+ def basic_forward
219
+ @pos += 1
220
+ @seq[@pos]
221
+ end
164
222
 
165
- protected
223
+ def basic_backward
224
+ r = @seq[@pos]
225
+ @pos -= 1; r
226
+ end
227
+
228
+ protected
229
+
230
+ # basic_current and basic_peek can be implemented more efficiently than in
231
+ # superclass
232
+ def basic_current
233
+ @seq[@pos]
234
+ end
166
235
 
167
- # basic_current and basic_peek can be implemented more efficiently than in
168
- # superclass
169
- def basic_current; @seq[@pos]; end
170
- def basic_peek; @seq[@pos+1]; end
236
+ def basic_peek
237
+ @seq[@pos + 1]
238
+ end
239
+ end
171
240
 
172
- end # CollectionStream
241
+ # CollectionStream
173
242
 
174
243
  # A simple Iterator for iterating over a sequence of integers starting from
175
244
  # zero up to a given upper bound. Mainly used by Stream::FilteredStream. Could
@@ -179,26 +248,44 @@ module Stream
179
248
  # The upper bound is stored in the instance variable @stop which can be
180
249
  # incremented dynamically by the method increment_stop.
181
250
  class IntervalStream < BasicStream
182
- attr_reader :pos
251
+ attr_reader :pos
252
+
253
+ # Create a new IntervalStream with upper bound _stop_. stop - 1 is the last
254
+ # element. By default _stop_ is zero which means that the stream is empty.
255
+ def initialize(stop = 0)
256
+ @stop = stop - 1
257
+ set_to_begin
258
+ end
259
+
260
+ def at_beginning?
261
+ @pos < 0
262
+ end
263
+
264
+ def at_end?
265
+ @pos == @stop
266
+ end
183
267
 
184
- # Create a new IntervalStream with upper bound _stop_. stop - 1 is the last
185
- # element. By default _stop_ is zero which means that the stream is empty.
186
- def initialize(stop=0)
187
- @stop = stop - 1
188
- set_to_begin
189
- end
268
+ def set_to_end
269
+ @pos = @stop
270
+ end
190
271
 
191
- def at_beginning?; @pos < 0; end
192
- def at_end?; @pos == @stop; end
272
+ def set_to_begin
273
+ @pos = -1
274
+ end
193
275
 
194
- def set_to_end; @pos = @stop; end
195
- def set_to_begin; @pos = -1; end
276
+ # Increment the upper bound by incr.
277
+ def increment_stop(incr = 1)
278
+ @stop += incr
279
+ end
196
280
 
197
- # Increment the upper bound by incr.
198
- def increment_stop(incr=1); @stop += incr; end
281
+ def basic_forward
282
+ @pos += 1
283
+ end
199
284
 
200
- def basic_forward; @pos += 1; end
201
- def basic_backward; @pos -= 1; @pos + 1; end
285
+ def basic_backward
286
+ @pos -= 1
287
+ @pos + 1
288
+ end
202
289
  end
203
290
 
204
291
  # Class WrappedStream is the abstract superclass for stream classes that wrap
@@ -211,25 +298,41 @@ module Stream
211
298
  # arrayStream.to_a => [1,2,3]
212
299
  # Stream::WrappedStream.new(arrayStream).to_a => [1,2,3]
213
300
  class WrappedStream < BasicStream
214
- attr_reader :wrapped_stream
301
+ attr_reader :wrapped_stream
302
+
303
+ # Create a new WrappedStream wrapping the Stream _other_stream_.
304
+ def initialize(other_stream)
305
+ @wrapped_stream = other_stream
306
+ end
307
+
308
+ def at_beginning?
309
+ @wrapped_stream.at_beginning?
310
+ end
215
311
 
216
- # Create a new WrappedStream wrapping the Stream _otherStream_.
217
- def initialize(otherStream)
218
- @wrapped_stream = otherStream
219
- end
312
+ def at_end?
313
+ @wrapped_stream.at_end?
314
+ end
220
315
 
221
- def at_beginning?; @wrapped_stream.at_beginning?; end
222
- def at_end?; @wrapped_stream.at_end?; end
316
+ def set_to_end
317
+ @wrapped_stream.set_to_end
318
+ end
223
319
 
224
- def set_to_end; @wrapped_stream.set_to_end; end
225
- def set_to_begin; @wrapped_stream.set_to_begin; end
320
+ def set_to_begin
321
+ @wrapped_stream.set_to_begin
322
+ end
226
323
 
227
- # Returns the wrapped stream unwrapped.
228
- def unwrapped; @wrapped_stream.unwrapped; end
324
+ # Returns the wrapped stream unwrapped.
325
+ def unwrapped
326
+ @wrapped_stream.unwrapped
327
+ end
229
328
 
230
- public # but should be protected. Would like to have a friend concept here.
231
- def basic_forward; @wrapped_stream.basic_forward; end
232
- def basic_backward; @wrapped_stream.basic_backward; end
329
+ def basic_forward
330
+ @wrapped_stream.basic_forward
331
+ end
332
+
333
+ def basic_backward
334
+ @wrapped_stream.basic_backward
335
+ end
233
336
  end
234
337
 
235
338
  ##
@@ -240,64 +343,69 @@ module Stream
240
343
  #
241
344
  # (1..6).create_stream.filtered { |x| x % 2 == 0 }.to_a ==> [2, 4, 6]
242
345
  class FilteredStream < WrappedStream
346
+ # Create a new FilteredStream wrapping _other_stream_ and selecting all its
347
+ # elements which satisfy the condition defined by the block_filter_.
348
+ def initialize(other_stream, &filter)
349
+ super other_stream
350
+ @filter = filter
351
+ @position_holder = IntervalStream.new
352
+ set_to_begin
353
+ end
243
354
 
244
- # Create a new FilteredStream wrapping _otherStream_ and selecting all its
245
- # elements which satisfy the condition defined by the block_filter_.
246
- def initialize(otherStream, &filter)
247
- super otherStream
248
- @filter = filter
249
- @positionHolder = IntervalStream.new
250
- set_to_begin
251
- end
252
-
253
- def at_beginning?; @positionHolder.at_beginning?; end
254
-
255
- # at_end? has to look ahead if there is an element satisfing the filter
256
- def at_end?
257
- @positionHolder.at_end? and
258
- begin
259
- if @peek.nil?
260
- @peek = wrapped_stream.move_forward_until( &@filter ) or return true
261
- @positionHolder.increment_stop
262
- end
263
- false
264
- end
265
- end
266
-
267
- def basic_forward
268
- result =
269
- if @peek.nil?
270
- wrapped_stream.move_forward_until(&@filter)
271
- else
272
- # Do not move!!
273
- @peek
274
- end
275
- @peek = nil
276
- @positionHolder.forward
277
- result
278
- end
279
-
280
- def basic_backward
281
- wrapped_stream.backward unless @peek.nil?
282
- @peek = nil
283
- @positionHolder.backward
284
- wrapped_stream.move_backward_until(&@filter) or self
285
- end
286
-
287
- def set_to_end
288
- # Not super which is a WrappedStream, but same behavior as in Stream
289
- until at_end?; basic_forward; end
290
- end
291
-
292
- def set_to_begin
293
- super
294
- @peek = nil
295
- @positionHolder.set_to_begin
296
- end
297
-
298
- # Returns the current position of the stream.
299
- def pos; @positionHolder.pos; end
300
- end # FilteredStream
355
+ def at_beginning?
356
+ @position_holder.at_beginning?
357
+ end
358
+
359
+ # at_end? has to look ahead if there is an element satisfing the filter
360
+ def at_end?
361
+ @position_holder.at_end? and
362
+ begin
363
+ if @peek.nil?
364
+ @peek = wrapped_stream.move_forward_until(&@filter) or return true
365
+ @position_holder.increment_stop
366
+ end
367
+ false
368
+ end
369
+ end
370
+
371
+ def basic_forward
372
+ result =
373
+ if @peek.nil?
374
+ wrapped_stream.move_forward_until(&@filter)
375
+ else
376
+ # Do not move!!
377
+ @peek
378
+ end
379
+ @peek = nil
380
+ @position_holder.forward
381
+ result
382
+ end
383
+
384
+ def basic_backward
385
+ wrapped_stream.backward unless @peek.nil?
386
+ @peek = nil
387
+ @position_holder.backward
388
+ wrapped_stream.move_backward_until(&@filter) or self
389
+ end
390
+
391
+ def set_to_end
392
+ # Not super which is a WrappedStream, but same behavior as in Stream
393
+ basic_forward until at_end?
394
+ end
395
+
396
+ def set_to_begin
397
+ super
398
+ @peek = nil
399
+ @position_holder.set_to_begin
400
+ end
401
+
402
+ # Returns the current position of the stream.
403
+ def pos
404
+ @position_holder.pos
405
+ end
406
+ end
407
+
408
+ # FilteredStream
301
409
 
302
410
  ##
303
411
  # Each reversable stream (a stream that implements #backward and
@@ -307,29 +415,43 @@ module Stream
307
415
  #
308
416
  # (1..6).create_stream.reverse.to_a ==> [6, 5, 4, 3, 2, 1]
309
417
  class ReversedStream < WrappedStream
418
+ # Create a reversing wrapper for the reversable stream _other_stream_. If
419
+ # _other_stream_ does not support backward moving a NotImplementedError is
420
+ # signaled on the first backward move.
421
+ def initialize(other_stream)
422
+ super other_stream
423
+ set_to_begin
424
+ end
310
425
 
311
- # Create a reversing wrapper for the reversable stream _otherStream_. If
312
- # _otherStream_ does not support backward moving a NotImplementedError is
313
- # signaled on the first backward move.
314
- def initialize(otherStream)
315
- super otherStream
316
- set_to_begin
317
- end
426
+ # Returns true if the wrapped stream is at_end?.
427
+ def at_beginning?
428
+ wrapped_stream.at_end?
429
+ end
318
430
 
319
- # Returns true if the wrapped stream is at_end?.
320
- def at_beginning?; wrapped_stream.at_end?; end
321
- # Returns true if the wrapped stream is at_beginning?.
322
- def at_end?; wrapped_stream.at_beginning?; end
431
+ # Returns true if the wrapped stream is at_beginning?.
432
+ def at_end?
433
+ wrapped_stream.at_beginning?
434
+ end
323
435
 
324
- # Moves the wrapped stream one step backward.
325
- def basic_forward; wrapped_stream.basic_backward; end
326
- # Moves the wrapped stream one step forward.
327
- def basic_backward; wrapped_stream.basic_forward; end
436
+ # Moves the wrapped stream one step backward.
437
+ def basic_forward
438
+ wrapped_stream.basic_backward
439
+ end
328
440
 
329
- # Sets the wrapped stream to the beginning.
330
- def set_to_end; wrapped_stream.set_to_begin; end
331
- # Sets the wrapped stream to the end.
332
- def set_to_begin; wrapped_stream.set_to_end; end
441
+ # Moves the wrapped stream one step forward.
442
+ def basic_backward
443
+ wrapped_stream.basic_forward
444
+ end
445
+
446
+ # Sets the wrapped stream to the beginning.
447
+ def set_to_end
448
+ wrapped_stream.set_to_begin
449
+ end
450
+
451
+ # Sets the wrapped stream to the end.
452
+ def set_to_begin
453
+ wrapped_stream.set_to_end
454
+ end
333
455
  end
334
456
 
335
457
  ##
@@ -341,21 +463,25 @@ module Stream
341
463
  # (1..5).collect {|x| x**2} ==> [1, 4, 9, 16, 25]
342
464
  # (1..5).create_stream.collect {|x| x**2}.to_a ==> [1, 4, 9, 16, 25]
343
465
  class MappedStream < WrappedStream
466
+ ##
467
+ # Creates a new MappedStream wrapping _other_stream_ which calls the block
468
+ # _mapping_ on each move.
469
+ def initialize(other_stream, &mapping)
470
+ super other_stream
471
+ @mapping = mapping
472
+ end
344
473
 
345
- ##
346
- # Creates a new MappedStream wrapping _otherStream_ which calls the block
347
- # _mapping_ on each move.
348
- def initialize(otherStream, &mapping)
349
- super otherStream
350
- @mapping = mapping
351
- end
474
+ # Apply the stored closure for the next element in the wrapped stream and
475
+ # return the result.
476
+ def basic_forward
477
+ @mapping.call(super)
478
+ end
352
479
 
353
- # Apply the stored closure for the next element in the wrapped stream and
354
- # return the result.
355
- def basic_forward; @mapping.call(super); end
356
- # Apply the stored closure for the previous element in the wrapped stream
357
- # and return the result.
358
- def basic_backward; @mapping.call(super); end
480
+ # Apply the stored closure for the previous element in the wrapped stream
481
+ # and return the result.
482
+ def basic_backward
483
+ @mapping.call(super)
484
+ end
359
485
  end
360
486
 
361
487
  ##
@@ -366,81 +492,98 @@ module Stream
366
492
  #
367
493
  # ((1..3).create_stream + [4,5].create_stream).to_a ==> [1, 2, 3, 4, 5]
368
494
  class ConcatenatedStream < WrappedStream
369
- alias :streamOfStreams :wrapped_stream
370
- private :streamOfStreams
371
-
372
- # Creates a new ConcatenatedStream wrapping the stream of streams
373
- # _streamOfStreams_.
374
- def initialize(streamOfStreams)
375
- super
376
- set_to_begin
377
- end
378
-
379
- # If the current stream is at end, than at_end? has to look ahead to find a
380
- # non empty in the stream of streams, which than gets the current stream.
381
- def at_end?
382
- if @currentStream.at_end?
495
+ alias streamOfStreams wrapped_stream
496
+ private :streamOfStreams
497
+
498
+ # Creates a new ConcatenatedStream wrapping the stream of streams
499
+ # _streamOfStreams_.
500
+ def initialize(streamOfStreams)
501
+ super
502
+ set_to_begin
503
+ end
504
+
505
+ # If the current stream is at end, than at_end? has to look ahead to find a
506
+ # non empty in the stream of streams, which than gets the current stream.
507
+ def at_end?
508
+ unless @current_stream.at_end?
383
509
  return false
384
- else
385
- until streamOfStreams.at_end?
386
- dir, @dirOfLastMove = @dirOfLastMove, :forward
387
- s = streamOfStreams.basic_forward
388
- # if last move was backwards, then @currentStream is
389
- # equivalent to s. Move to next stream.
390
- next if dir == :backward
391
- s.set_to_begin
392
- if s.at_end? # empty stream?
393
- next # skip it
394
- else
395
- @currentStream = s
396
- return false # found non empty stream
397
- end
398
- end # until
399
- reachedBoundary # sets @dirOfLastMove and @currentStream
400
510
  end
511
+
512
+ until streamOfStreams.at_end?
513
+ dir = @dir_of_last_move
514
+ @dir_of_last_move = :forward
515
+ s = streamOfStreams.basic_forward
516
+ # if last move was backwards, then @current_stream is
517
+ # equivalent to s. Move to next stream.
518
+ next if dir == :backward
519
+
520
+ s.set_to_begin
521
+ if s.at_end? # empty stream?
522
+ next # skip it
523
+ else
524
+ @current_stream = s
525
+ return false # found non empty stream
526
+ end
527
+ end # until
528
+ reached_boundary # sets @dir_of_last_move and @current_stream
401
529
  end
402
530
 
403
- # Same as at_end? the other way round.
531
+ # Same as at_end? the other way round.
532
+ # @return [Boolean]
404
533
  def at_beginning?
405
- # same algorithm as at_end? the other way round.
406
- if @currentStream.at_beginning?
534
+ # same algorithm as at_end? the other way round.
535
+ unless @current_stream.at_beginning?
407
536
  return false
408
- else
409
- until streamOfStreams.at_beginning?
410
- dir, @dirOfLastMove = @dirOfLastMove, :backward
411
- s = streamOfStreams.basic_backward
412
- next if dir == :forward
413
- s.set_to_end
414
- if s.at_beginning?
415
- next
416
- else
417
- @currentStream = s
418
- return false
419
- end
420
- end
421
- reachedBoundary
422
- end
423
- end
424
-
425
- def set_to_begin; super; reachedBoundary end
426
- def set_to_end; super; reachedBoundary end
427
-
428
- # Returns the next element of @currentStream. at_end? ensured that there is
429
- # one.
430
- def basic_forward; @currentStream.basic_forward end
431
- # Returns the previous element of @currentStream. at_beginning? ensured that
432
- # there is one.
433
- def basic_backward; @currentStream.basic_backward end
434
-
435
- private
436
-
437
- def reachedBoundary
438
- @currentStream = EmptyStream.instance
439
- @dirOfLastMove = :none # not :forward or :backward
440
- true
441
- end
442
- # Uff, this was the hardest stream to implement.
443
- end # ConcatenatedStream
537
+ end
538
+
539
+ until streamOfStreams.at_beginning?
540
+ dir = @dir_of_last_move
541
+ @dir_of_last_move = :backward
542
+ s = streamOfStreams.basic_backward
543
+ next if dir == :forward
544
+
545
+ s.set_to_end
546
+ if s.at_beginning?
547
+ next
548
+ else
549
+ @current_stream = s
550
+ return false
551
+ end
552
+ end
553
+ reached_boundary
554
+ end
555
+
556
+ def set_to_begin
557
+ super; reached_boundary
558
+ end
559
+
560
+ def set_to_end
561
+ super; reached_boundary
562
+ end
563
+
564
+ # Returns the next element of @current_stream. at_end? ensured that there is
565
+ # one.
566
+ def basic_forward
567
+ @current_stream.basic_forward
568
+ end
569
+
570
+ # Returns the previous element of @current_stream. at_beginning? ensured that
571
+ # there is one.
572
+ def basic_backward
573
+ @current_stream.basic_backward
574
+ end
575
+
576
+ private
577
+
578
+ def reached_boundary
579
+ @current_stream = EmptyStream.instance
580
+ @dir_of_last_move = :none # not :forward or :backward
581
+ true
582
+ end
583
+ # Uff, this was the hardest stream to implement.
584
+ end
585
+
586
+ # ConcatenatedStream
444
587
 
445
588
  # An ImplicitStream is an easy way to create a stream on the fly without
446
589
  # defining a subclass of BasicStream. The basic methods required for a stream
@@ -463,72 +606,96 @@ module Stream
463
606
  # remove the first or last element of an existing stream (see remove_first
464
607
  # and remove_last).
465
608
  class ImplicitStream < BasicStream
466
- attr_writer :at_beginning_proc, :at_end_proc, :forward_proc,
609
+ attr_writer :at_beginning_proc, :at_end_proc, :forward_proc,
467
610
  :backward_proc, :set_to_begin_proc, :set_to_end_proc
468
- attr_reader :wrapped_stream
469
-
470
- # Create a new ImplicitStream which might wrap an existing stream
471
- # _otherStream_. If _otherStream_ is supplied the blocks for the basic
472
- # stream methods are initialized with closures that delegate all operations
473
- # to the wrapped stream.
474
- #
475
- # If a block is given to new, than it is called with the new ImplicitStream
476
- # stream as parameter letting the client overwriting the default blocks.
477
- def initialize(otherStream=nil)
478
- if otherStream
479
- @wrapped_stream = otherStream
480
- @at_beginning_proc = proc {otherStream.at_beginning?}
481
- @at_end_proc = proc {otherStream.at_end?}
482
- @forward_proc = proc {otherStream.basic_forward}
483
- @backward_proc = proc {otherStream.basic_backward}
484
- @set_to_end_proc = proc {otherStream.set_to_end}
485
- @set_to_begin_proc = proc {otherStream.set_to_begin}
486
- end
487
- yield self if block_given? # let client overwrite defaults
488
-
489
- @at_beginning_proc = proc {true} unless @at_beginning_proc
490
- @at_end_proc = proc {true} unless @at_end_proc
491
- end
492
-
493
- # Returns the value of @at_beginning_proc.
494
- def at_beginning?; @at_beginning_proc.call; end
495
- # Returns the value of @at_end_proc.
496
- def at_end?; @at_end_proc.call; end
497
-
498
- # Returns the value of @forward_proc.
499
- def basic_forward; @forward_proc.call; end
500
- # Returns the value of @backward_proc_proc.
501
- def basic_backward; @backward_proc.call; end
502
-
503
- # Calls set_to_end_proc or super if set_to_end_proc is undefined.
504
- def set_to_end
505
- @set_to_end_proc ? @set_to_end_proc.call : super
506
- end
507
-
508
- # Calls set_to_begin_proc or super if set_to_begin_proc is undefined.
509
- def set_to_begin
510
- @set_to_begin_proc ? @set_to_begin_proc.call : super
511
- end
512
- end # ImplicitStream
611
+ attr_reader :wrapped_stream
612
+
613
+ # Create a new ImplicitStream which might wrap an existing stream
614
+ # _other_stream_. If _other_stream_ is supplied the blocks for the basic
615
+ # stream methods are initialized with closures that delegate all operations
616
+ # to the wrapped stream.
617
+ #
618
+ # If a block is given to new, than it is called with the new ImplicitStream
619
+ # stream as parameter letting the client overwriting the default blocks.
620
+ def initialize(other_stream = nil)
621
+ # Initialize with defaults
622
+ @at_beginning_proc = proc { true }
623
+ @at_end_proc = proc { true }
624
+
625
+ @set_to_begin_proc = proc {}
626
+ @set_to_end_proc = proc {}
627
+
628
+ if other_stream
629
+ @wrapped_stream = other_stream
630
+ @at_beginning_proc = proc { other_stream.at_beginning? }
631
+ @at_end_proc = proc { other_stream.at_end? }
632
+ @forward_proc = proc { other_stream.basic_forward }
633
+ @backward_proc = proc { other_stream.basic_backward }
634
+ @set_to_end_proc = proc { other_stream.set_to_end }
635
+ @set_to_begin_proc = proc { other_stream.set_to_begin }
636
+ end
637
+ yield self if block_given? # let client overwrite defaults
638
+ end
639
+
640
+ # Returns the value of @at_beginning_proc.
641
+ def at_beginning?
642
+ @at_beginning_proc.call
643
+ end
644
+
645
+ # Returns the value of @at_end_proc.
646
+ def at_end?
647
+ @at_end_proc.call
648
+ end
649
+
650
+ # Returns the value of @forward_proc.
651
+ def basic_forward
652
+ @forward_proc.call
653
+ end
654
+
655
+ # Returns the value of @backward_proc_proc.
656
+ def basic_backward
657
+ @backward_proc.call
658
+ end
659
+
660
+ # Calls set_to_end_proc or super if set_to_end_proc is undefined.
661
+ def set_to_end
662
+ @set_to_end_proc ? @set_to_end_proc.call : super
663
+ end
664
+
665
+ # Calls set_to_begin_proc or super if set_to_begin_proc is undefined.
666
+ def set_to_begin
667
+ @set_to_begin_proc ? @set_to_begin_proc.call : super
668
+ end
669
+ end
670
+
671
+ # ImplicitStream
513
672
 
514
673
  # Stream creation functions
515
674
 
516
675
  ##
517
676
  # Return a Stream::FilteredStream which iterates over all my elements
518
677
  # satisfying the condition specified by the block.
519
- def filtered(&block); FilteredStream.new(self,&block); end
678
+ def filtered(&block)
679
+ FilteredStream.new(self, &block)
680
+ end
520
681
 
521
682
  # Create a Stream::ReversedStream wrapper on self.
522
- def reverse; ReversedStream.new self; end
683
+ def reverse
684
+ ReversedStream.new self
685
+ end
523
686
 
524
687
  # Create a Stream::MappedStream wrapper on self. Instead of returning the
525
688
  # stream element on each move, the value of calling _mapping_ is returned
526
689
  # instead. See Stream::MappedStream for examples.
527
- def collect(&mapping); MappedStream.new(self, &mapping); end
690
+ def collect(&mapping)
691
+ MappedStream.new(self, &mapping)
692
+ end
528
693
 
529
694
  # Create a Stream::ConcatenatedStream on self, which must be a stream of
530
695
  # streams.
531
- def concatenate; ConcatenatedStream.new self; end
696
+ def concatenate
697
+ ConcatenatedStream.new self
698
+ end
532
699
 
533
700
  # Create a Stream::ConcatenatedStream, concatenated from streams build with
534
701
  # the block for each element of self:
@@ -537,33 +704,37 @@ module Stream
537
704
  # [i,-i].create_stream
538
705
  # }.
539
706
  # s.to_a ==> [1, -1, 2, -2, 3, -3]
540
- def concatenate_collected(&mapping); self.collect(&mapping).concatenate; end
707
+ def concatenate_collected(&mapping)
708
+ collect(&mapping).concatenate
709
+ end
541
710
 
542
711
  # Create a Stream::ConcatenatedStream by concatenatating the receiver and
543
- # _otherStream_
712
+ # _other_stream_
544
713
  #
545
714
  # (%w(a b c).create_stream + [4,5].create_stream).to_a
546
715
  # ==> ["a", "b", "c", 4, 5]
547
- def +(otherStream)
548
- [self, otherStream].create_stream.concatenate
716
+ def +(other)
717
+ [self, other].create_stream.concatenate
549
718
  end
550
719
 
551
720
  # Create a Stream::ImplicitStream which wraps the receiver stream by modifying
552
721
  # one or more basic methods of the receiver. As an example the method
553
722
  # remove_first uses #modify to create an ImplicitStream which filters the
554
723
  # first element away.
555
- def modify(&block); ImplicitStream.new(self, &block); end
724
+ def modify(&block)
725
+ ImplicitStream.new(self, &block)
726
+ end
556
727
 
557
728
  # Returns a Stream::ImplicitStream wrapping a Stream::FilteredStream, which
558
729
  # eliminates the first element of the receiver.
559
730
  #
560
731
  # (1..3).create_stream.remove_first.to_a ==> [2,3]
561
732
  def remove_first
562
- i = 0
563
- filter = self.filtered { i += 1; i > 1 }
564
- filter.modify { |s|
565
- s.set_to_begin_proc = proc {filter.set_to_begin; i = 0}
566
- }
733
+ i = 0
734
+ filter = filtered { i += 1; i > 1 }
735
+ filter.modify do |s|
736
+ s.set_to_begin_proc = proc { filter.set_to_begin; i = 0 }
737
+ end
567
738
  end
568
739
 
569
740
  # Returns a Stream which eliminates the first element of the receiver.
@@ -573,7 +744,7 @@ module Stream
573
744
  # <em>Take a look at the source. The implementation is inefficient but
574
745
  # elegant.</em>
575
746
  def remove_last
576
- self.reverse.remove_first.reverse # I like this one
747
+ reverse.remove_first.reverse # I like this one
577
748
  end
578
749
  end
579
750