stream 0.5.2 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
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