stream 0.5.4 → 0.5.6

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: 55354ecc39933e7f4be1b3b1eaa9bcfec109b00346f739e2f6c675a333ed17e9
4
- data.tar.gz: aab007abb0bf1bf998be99a9806d3e3d9a8f305a422ce01ac83ea586b42a778a
3
+ metadata.gz: 1a1851af382462908d89f216b7b68c4e12a471bf66c8b95f68a8770bce964d5c
4
+ data.tar.gz: cae0261438776cd1b62c70686ec6a9983b45ecabc2476b37d88b9c6a43868272
5
5
  SHA512:
6
- metadata.gz: 416c8fe937cc016744b8325bd3f15a6210a51fe17900de8e1db8b405ef5793cd2344ff3f0e9b0a3e336bf71c1497b9f84137238f4f92431fa861056f6a34646c
7
- data.tar.gz: c07f8c66b7ca2d3a3e7c355b9b7bdbb6bd3151c9871159b0c92376773a732b9fdbabc2e1727f6b4c822b4412aa67a17f0601afd969f50ecd1a9751618e4c72e3
6
+ metadata.gz: ae065f33f579bde4192dfb75f4fc6dd57f20f40708c1614eb236364e4cf61b5848e11f2fa00e29c54f6b63af37135d8c5dd3782336d02c43b50d18742b29d121
7
+ data.tar.gz: 673f7510857e58e5f31b07edf304cce64a1f999f5433ba7c4305dd0ae4eb27aeb01135ab5be314155b22053a80915e91bfc3451e3860a74da710137bbfedc4ef
data/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ # Changelog
2
+
3
+ ## [0.5.6](https://github.com/monora/stream/compare/v0.5.5...v0.5.6) (2026-05-10)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * convert README to Markdown, add copyright, fix badges, clean up ([#16](https://github.com/monora/stream/issues/16)) ([9716019](https://github.com/monora/stream/commit/97160196497cb568ae2558b03d6ac4fc0e267a65))
data/Gemfile.lock CHANGED
@@ -1,19 +1,15 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- stream (0.5.4)
5
- generator
4
+ stream (0.5.6)
6
5
 
7
6
  GEM
8
7
  remote: https://rubygems.org/
9
8
  specs:
10
- generator (0.0.1)
11
- power_assert (1.1.3)
12
- rake (12.3.2)
13
- rdoc (6.1.1)
14
- test-unit (3.2.9)
9
+ power_assert (3.0.1)
10
+ rake (13.4.2)
11
+ test-unit (3.7.7)
15
12
  power_assert
16
- yard (0.9.16)
17
13
 
18
14
  PLATFORMS
19
15
  ruby
@@ -21,10 +17,8 @@ PLATFORMS
21
17
 
22
18
  DEPENDENCIES
23
19
  rake
24
- rdoc
25
20
  stream!
26
21
  test-unit
27
- yard
28
22
 
29
23
  BUNDLED WITH
30
- 2.3.8
24
+ 2.5.22
data/LICENSE CHANGED
@@ -1,3 +1,7 @@
1
+ Copyright (c) 2002-2026 Horst Duchene <monora@gmail.com>
2
+
3
+ stream is distributed under the same license as Ruby.
4
+
1
5
  Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.jp>.
2
6
  You can redistribute it and/or modify it under either the terms of the
3
7
  2-clause BSDL (see the file BSDL), or the conditions below:
data/README.md ADDED
@@ -0,0 +1,209 @@
1
+ [![Build Status](https://github.com/monora/stream/actions/workflows/ruby.yml/badge.svg)](https://github.com/monora/stream/actions/workflows/ruby.yml)
2
+ [![Version](https://img.shields.io/gem/v/stream.svg)](https://rubygems.org/gems/stream)
3
+
4
+ # Extended External Iterators (forward and backward)
5
+
6
+ ## Description
7
+
8
+ Module `Stream` defines an interface for [external
9
+ iterators](https://wiki.c2.com/?ExternalIterator). A stream can be seen
10
+ as an iterator on a sequence of objects `x1,...,xn`. The state of the
11
+ stream is uniquely determined by the following methods:
12
+
13
+ * `at_beginning?`
14
+ * `at_end?`
15
+ * `current`
16
+ * `peek`
17
+
18
+ State changes are done with the following operations:
19
+
20
+ * `set_to_begin`
21
+ * `set_to_end`
22
+ * `forward`
23
+ * `backward`
24
+
25
+ With the help of the method `current_edge` the state of a stream `s` can be
26
+ exactly defined
27
+
28
+ ```
29
+ s.current_edge == [s.current, s.peek]
30
+ ```
31
+
32
+ If `s` a stream on `[x1,...,xn]`. Consider the edges `[xi,xi+1]` i=1,...,n
33
+ and `[x0,x1]` and `[xn,xn+1]` (x0 and xn+1 are helper elements to define
34
+ the boundary conditions). Then if `s` is non empty, the following
35
+ conditions must be true:
36
+
37
+ ```
38
+ s.at_beginning? <=> s.current_edge == [x0,x1]
39
+ s.at_end? <=> s.current_edge == [xn,xn+1]
40
+ s.empty? <=> s.at_beginning? && s.at_end? <=> s.current_edge == [x0,x1] <=> n = 0
41
+ s.set_to_end => s.at_end?
42
+ s.set_to_begin => s.at_beginning?
43
+ ```
44
+
45
+ If `0 <= i < n` and `s.current_edge == [xi, xi+1]`, then:
46
+
47
+ ```
48
+ [s.forward, s.current_edge] == [xi+1, [xi+1, xi+2]]
49
+ ```
50
+
51
+ If `1 <= i < n` and `s.current_edge == [xi, xi+1]`, then:
52
+
53
+ ```
54
+ [s.backward, s.current_edge] == [xi, [xi-1, xi]]
55
+ ```
56
+
57
+ The result of `peek` is the same as of `forward` without changing state. The result of
58
+ `current` is the same as of `backward` without changing state.
59
+
60
+ Module `Stream` includes `Enumerable` implementing `each` in the obvious way.
61
+
62
+ Not every stream needs to implement `backward` and `at_beginning?`
63
+ thus being not reversable. If they are reversable `peek` can easily be
64
+ implemented using `forward` and `backward`, as is done in module
65
+ `Stream`. If a stream is not reversable all derived streams provided
66
+ by the stream module (filter, mapping, concatenation) can be used
67
+ anyway. Explicit or implicit (via `peek` or `current`) uses of `backward`
68
+ would throw a `NotImplementedError`.
69
+
70
+ Classes implementing the stream interface must implement the following
71
+ methods:
72
+
73
+ * `basic_forward`
74
+ * `basic_backward`
75
+ * `at_end?`
76
+ * `at_beginning?`
77
+
78
+ The methods `set_to_end` and `set_to_begin` are by default implemented as:
79
+
80
+ ```
81
+ set_to_end : until at_end?; do basic_forward end
82
+ set_to_begin : until at_beginning?; do basic_backward end
83
+ ```
84
+
85
+ The methods `forward` and `backward` are by default implemented as:
86
+
87
+ ```
88
+ forward: raise EndOfStreamException if at_end?; basic_forward.
89
+ backward: raise EndOfStreamException if at_beginning?; basic_backward
90
+ ```
91
+
92
+ Thus subclasses must only implement **four** methods. Efficiency sometimes
93
+ demands better implementations.
94
+
95
+ There are several concrete classes implementing the stream interface:
96
+
97
+ * `Stream::EmptyStream` (boring)
98
+ * `Stream::CollectionStream` created by the method `Array#create_stream`
99
+ * `Stream::FilteredStream` created by the method `Stream#filtered`
100
+ * `Stream::ReversedStream` created by the method `Stream#reverse`
101
+ * `Stream::ConcatenatedStream` created by the method `Stream#concatenate`
102
+ * `Stream::ImplicitStream` using closures for the basic methods to implement
103
+
104
+ ## Installation
105
+
106
+ ```bash
107
+ gem install stream
108
+ ```
109
+
110
+ or download the latest sources from the git repository
111
+ <https://github.com/monora/stream>.
112
+
113
+ ## Examples
114
+
115
+ ### Iterate over three streams
116
+
117
+ ```ruby
118
+ g = ('a'..'f').create_stream
119
+ h = (1..10).create_stream
120
+ i = (10..20).create_stream
121
+
122
+ until g.at_end? || h.at_end? || i.at_end?
123
+ p [g.forward, h.forward, i.forward]
124
+ end
125
+ ```
126
+
127
+ Output:
128
+
129
+ ```
130
+ ["a", 1, 10]
131
+ ["b", 2, 11]
132
+ ["c", 3, 12]
133
+ ["d", 4, 13]
134
+ ["e", 5, 14]
135
+ ["f", 6, 15]
136
+ ```
137
+
138
+ ### Concatenate file streams
139
+
140
+ ```ruby
141
+ def filestream fname
142
+ Stream::ImplicitStream.new { |s|
143
+ f = open(fname)
144
+ s.at_end_proc = proc {f.eof?}
145
+ s.forward_proc = proc {f.readline}
146
+ # Need not implement backward moving to use the framework
147
+ }
148
+ end
149
+
150
+ (filestream("/etc/passwd") + ('a'..'f').create_stream + filestream("/etc/group")).each do |l|
151
+ puts l
152
+ end
153
+ ```
154
+
155
+ ### Two filtered collection streams concatenated and reversed
156
+
157
+ ```ruby
158
+ def newstream; (1..6).create_stream; end
159
+ s = newstream.filtered { |x| x % 2 == 0 } + newstream.filtered { |x| x % 2 != 0 }
160
+ s = s.reverse
161
+ puts "Contents : #{s.to_a.join ' '}"
162
+ puts "At end? : #{s.at_end?}"
163
+ puts "At beginning? : #{s.at_beginning?}"
164
+ puts "2xBackwards : #{s.backward} #{s.backward}"
165
+ puts "Forward : #{s.forward}"
166
+ puts "Peek : #{s.peek}"
167
+ puts "Current : #{s.current}"
168
+ puts "set_to_begin : Peek=#{s.set_to_begin;s.peek}"
169
+ ```
170
+
171
+ Output:
172
+
173
+ ```
174
+ Contents : 5 3 1 6 4 2
175
+ At end? : true
176
+ At beginning? : false
177
+ 2xBackwards : 2 4
178
+ Forward : 4
179
+ Peek : 2
180
+ Current : 4
181
+ set_to_begin : Peek=5
182
+ ```
183
+
184
+ ### An infinite stream (do not use `set_to_end`!)
185
+
186
+ ```ruby
187
+ def randomStream
188
+ Stream::ImplicitStream.new { |s|
189
+ s.set_to_begin_proc = proc {srand 1234}
190
+ s.at_end_proc = proc {false}
191
+ s.forward_proc = proc {rand}
192
+ }
193
+ end
194
+ s = randomStream.filtered { |x| x >= 0.5 }.collect { |x| sprintf("%5.2f",x*100) }
195
+ puts "5 random numbers: #{(1..5).collect {|x| s.forward}}\n"
196
+ ```
197
+
198
+ Output:
199
+
200
+ ```
201
+ 5 random numbers: ["62.21", "78.54", "78.00", "80.19", "95.81"]
202
+ ```
203
+
204
+ ## Copying
205
+
206
+ stream is Copyright (c) 2002-2026 by Horst Duchene.
207
+
208
+ It is free software, and may be redistributed under the terms specified
209
+ in the [LICENSE](LICENSE) file.
data/Rakefile CHANGED
@@ -1,25 +1,12 @@
1
1
  # Rakefile for stream -*- ruby -*-
2
2
 
3
- require 'rubygems'
4
3
  require 'bundler/setup'
5
- require 'rubygems/package_task'
6
4
 
7
5
  require 'rake/testtask'
8
- require 'rake/clean'
9
- require 'yard'
10
-
11
- $:.unshift File.join(File.dirname(__FILE__), 'lib')
12
- require 'stream' # require module to STREAM_VERSION
13
-
14
- SRC_RB = FileList['lib/*.rb']
15
-
16
- # The default task is run if rake is given no explicit arguments.
17
6
 
18
7
  desc "Default Task"
19
8
  task :default => :test
20
9
 
21
- # Define a test task.
22
-
23
10
  Rake::TestTask.new do |t|
24
11
  t.libs << 'test'
25
12
  t.pattern = 'test/test*.rb'
@@ -28,23 +15,4 @@ end
28
15
 
29
16
  task :test
30
17
 
31
- # Define a test that will run all the test targets.
32
- desc "Run all test targets"
33
- task :testall => [:test ]
34
-
35
- # Git tagging
36
-
37
- desc "Commit all changes as a new version commit. Tag the commit with v<version> tag"
38
- task :tag do
39
- puts "Committing and tagging version #{STREAM_VERSION}"
40
- `git commit -am 'Version #{STREAM_VERSION}'`
41
- `git tag 'v#{STREAM_VERSION}'`
42
- end
43
-
44
- # Documentation
45
-
46
- YARD::Rake::YardocTask.new
47
-
48
- # Tasks for building and installing Stream gem.
49
-
50
18
  Bundler::GemHelper.install_tasks
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Stream
4
+ VERSION = '0.5.6'
5
+ end
data/lib/stream.rb CHANGED
@@ -1,4 +1,6 @@
1
- STREAM_VERSION = '0.5.4'.freeze
1
+ # frozen_string_literal: true
2
+
3
+ require 'stream/version'
2
4
 
3
5
  ##
4
6
  # Module Stream defines an interface for an external Iterator which
@@ -24,15 +26,17 @@ module Stream
24
26
  end
25
27
 
26
28
  # Move forward one position. Returns the _target_ of current_edge.
27
- # Raises Stream::EndOfStreamException if at_end? is true.
29
+ # @raise [EndOfStreamException] if at_end? is true
30
+ # @return [Object] the next element
28
31
  def forward
29
32
  raise EndOfStreamException if at_end?
30
33
 
31
34
  basic_forward
32
35
  end
33
36
 
34
- # Move backward one position. Returns the _source_ of current_edge. Raises
35
- # Stream::EndOfStreamException if at_beginning? is true.
37
+ # Move backward one position. Returns the _source_ of current_edge.
38
+ # @raise [EndOfStreamException] if at_beginning? is true
39
+ # @return [Object] the previous element
36
40
  def backward
37
41
  raise EndOfStreamException if at_beginning?
38
42
 
@@ -79,6 +83,8 @@ module Stream
79
83
  # This is similar to #detect, but starts the search from the
80
84
  # current position. #detect, which is inherited from Enumerable uses
81
85
  # #each, which implicitly calls #set_to_begin.
86
+ # @yield [element] each element in forward direction
87
+ # @return [Object, nil] the first matching element, or nil
82
88
  def move_forward_until
83
89
  until at_end?
84
90
  element = basic_forward
@@ -89,6 +95,8 @@ module Stream
89
95
 
90
96
  # Move backward until the boolean block is not false and returns the element
91
97
  # found. Returns nil if no object matches.
98
+ # @yield [element] each element in backward direction
99
+ # @return [Object, nil] the first matching element, or nil
92
100
  def move_backward_until
93
101
  until at_beginning?
94
102
  element = basic_backward
@@ -192,6 +200,7 @@ module Stream
192
200
  attr_reader :pos
193
201
 
194
202
  # Creates a new CollectionStream for the indexable sequence _seq_.
203
+ # @param seq [Array] an integer-indexed collection
195
204
  def initialize(seq)
196
205
  @seq = seq
197
206
  set_to_begin
@@ -252,6 +261,7 @@ module Stream
252
261
 
253
262
  # Create a new IntervalStream with upper bound _stop_. stop - 1 is the last
254
263
  # element. By default _stop_ is zero which means that the stream is empty.
264
+ # @param stop [Integer] exclusive upper bound; stream yields 0..stop-1
255
265
  def initialize(stop = 0)
256
266
  @stop = stop - 1
257
267
  set_to_begin
@@ -617,6 +627,8 @@ module Stream
617
627
  #
618
628
  # If a block is given to new, than it is called with the new ImplicitStream
619
629
  # stream as parameter letting the client overwriting the default blocks.
630
+ # @param other_stream [Stream, nil] optional stream to wrap
631
+ # @yield [self] the new ImplicitStream instance for customization
620
632
  def initialize(other_stream = nil)
621
633
  # Initialize with defaults
622
634
  @at_beginning_proc = proc { true }
@@ -674,7 +686,9 @@ module Stream
674
686
 
675
687
  ##
676
688
  # Return a Stream::FilteredStream which iterates over all my elements
677
- # satisfying the condition specified by the block.
689
+ # satisfying the condition specified by the block.
690
+ # @yield [element] filter predicate
691
+ # @return [FilteredStream]
678
692
  def filtered(&block)
679
693
  FilteredStream.new(self, &block)
680
694
  end
@@ -687,6 +701,8 @@ module Stream
687
701
  # Create a Stream::MappedStream wrapper on self. Instead of returning the
688
702
  # stream element on each move, the value of calling _mapping_ is returned
689
703
  # instead. See Stream::MappedStream for examples.
704
+ # @yield [element] mapping block applied to each element
705
+ # @return [MappedStream]
690
706
  def collect(&mapping)
691
707
  MappedStream.new(self, &mapping)
692
708
  end
@@ -708,8 +724,10 @@ module Stream
708
724
  collect(&mapping).concatenate
709
725
  end
710
726
 
711
- # Create a Stream::ConcatenatedStream by concatenatating the receiver and
712
- # _other_stream_
727
+ # Create a Stream::ConcatenatedStream by concatenating the receiver and
728
+ # _other_stream_.
729
+ # @param other [Stream] the stream to append
730
+ # @return [ConcatenatedStream]
713
731
  #
714
732
  # (%w(a b c).create_stream + [4,5].create_stream).to_a
715
733
  # ==> ["a", "b", "c", 4, 5]
data/test/test_helper.rb CHANGED
@@ -1,2 +1 @@
1
- require 'rubygems'
2
1
  require 'test/unit'
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stream
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.4
4
+ version: 0.5.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Horst Duchene
8
- autorequire: stream
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-06-02 00:00:00.000000000 Z
11
+ date: 2026-05-10 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: generator
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: rake
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -38,34 +24,6 @@ dependencies:
38
24
  - - ">="
39
25
  - !ruby/object:Gem::Version
40
26
  version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: yard
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: rdoc
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
27
  - !ruby/object:Gem::Dependency
70
28
  name: test-unit
71
29
  requirement: !ruby/object:Gem::Requirement
@@ -84,17 +42,18 @@ description: Module Stream defines an interface for external iterators.
84
42
  email: monora@gmail.com
85
43
  executables: []
86
44
  extensions: []
87
- extra_rdoc_files:
88
- - README.rdoc
45
+ extra_rdoc_files: []
89
46
  files:
47
+ - CHANGELOG.md
90
48
  - Gemfile
91
49
  - Gemfile.lock
92
50
  - LICENSE
93
- - README.rdoc
51
+ - README.md
94
52
  - Rakefile
95
53
  - examples/examples.rb
96
54
  - examples/streamtester.rb
97
55
  - lib/stream.rb
56
+ - lib/stream/version.rb
98
57
  - test/test_helper.rb
99
58
  - test/teststream.rb
100
59
  homepage: https://github.com/monora/stream
@@ -102,12 +61,7 @@ licenses:
102
61
  - ruby
103
62
  metadata: {}
104
63
  post_install_message:
105
- rdoc_options:
106
- - "--title"
107
- - stream - Extended External Iterators
108
- - "--main"
109
- - README.rdoc
110
- - "--line-numbers"
64
+ rdoc_options: []
111
65
  require_paths:
112
66
  - lib
113
67
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -121,7 +75,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
121
75
  - !ruby/object:Gem::Version
122
76
  version: '0'
123
77
  requirements: []
124
- rubygems_version: 3.2.3
78
+ rubygems_version: 3.5.22
125
79
  signing_key:
126
80
  specification_version: 4
127
81
  summary: stream - Extended External Iterators
data/README.rdoc DELETED
@@ -1,172 +0,0 @@
1
- {<img src="https://github.com/monora/stream/actions/workflows/ruby.yml/badge.svg" alt="Build Status" />}[https://github.com/monora/stream/actions/workflows/ruby.yml]
2
-
3
- = Extended External Iterators (forward and backward)
4
-
5
- == Description
6
-
7
- Module Stream defines an interface for external iterators. A stream can be
8
- seen as an iterator on a sequence of objects x1,...,xn. The state of the
9
- stream is uniquely determined by the following methods:
10
-
11
- * at_beginning?
12
- * at_end?
13
- * current
14
- * peek
15
-
16
- State changes are done with the following operations:
17
-
18
- * set_to_begin
19
- * set_to_end
20
- * forward
21
- * backward
22
-
23
- With the help of the method current_edge the state of a stream s can be
24
- exactly defined
25
-
26
- s.current_edge == [s.current, s.peek]
27
-
28
- If s a stream on [x1,...,xn]. Consider the edges [xi,xi+1] i=1,...,n and
29
- [x0,x1] and [xn,xn+1] (x0 and xn+1 are helper elements to define the boundary
30
- conditions). Then if s is non empty, the following conditions must be true:
31
-
32
- s.at_beginning? <=> s.current_edge == [x0,x1]
33
- s.at_end? <=> s.current_edge == [xn,xn+1]
34
- s.isEmpty? <=> s.at_beginning? && s.at_end? <=> s.current_edge == [x0,x1] <=> n = 0
35
- s.set_to_end => s.at_end?
36
- s.set_to_begin => s.at_beginning?
37
-
38
- If 0 <= i < n and s.current_edge == [xi, xi+1] , then:
39
-
40
- [s.forward, s.current_edge] == [xi+1, [xi+1, xi+2]]
41
-
42
- If 1 <= i < n and s.current_edge == [xi, xi+1] , then:
43
-
44
- [s.backward, s.current_edge] == [xi, [xi-1, xi]]
45
-
46
- The result of peek is the same as of forward without changing state. The result of
47
- current is the same as of backward without changing state.
48
-
49
- Module Stream includes Enumerable implementing #each in the obvious way.
50
-
51
- Not every stream needs to implement #backward and #at_beginning? thus being
52
- not reversable. If they are reversable peek can easily be implemented using
53
- forward and backward, as is done in module Stream. If a stream is not
54
- reversable all derived streams provided by the stream module (filter,
55
- mapping, concatenation) can be used anyway. Explicit or implicit (via peek or
56
- current) uses of backward would throw a NotImplementedError.
57
-
58
- Classes implementing the stream interface must implement the following methods:
59
-
60
- * basic_forward
61
- * basic_backward
62
-
63
- * at_end?
64
- * at_beginning?
65
-
66
- The methods set_to_end and set_to_begin are by default implemented as:
67
-
68
- set_to_end : until at_end?; do basic_forward end
69
- set_to_begin : until at_beginning?; do basic_backward end
70
-
71
- The methods forward and backward are by default implemented as:
72
-
73
- forward: raise EndOfStreamException if at_end?; basic_forward.
74
- backward: raise EndOfStreamException if at_beginning?; basic_backward
75
-
76
- Thus subclasses must only implement *four* methods. Efficiency sometimes
77
- demands better implementations.
78
-
79
- There are several concrete classes implementing the stream interface:
80
-
81
- * Stream::EmptyStream (boring)
82
- * Stream::CollectionStream created by the method Array#create_stream
83
- * Stream::FilteredStream created by the method Stream#filtered
84
- * Stream::ReversedStream created by the method Stream#reverse
85
- * Stream::ConcatenatedStream created by the method Stream#concatenate
86
- * Stream::ImplicitStream using closures for the basic methods to implement
87
-
88
- == Download
89
-
90
- The latest version of stream.rb can be found at
91
-
92
- * http://github.com/monora/stream
93
-
94
- == Installation
95
-
96
- === Normal Installation
97
-
98
- You can install stream with the following command.
99
-
100
- % ruby install.rb
101
-
102
- from its distribution directory.
103
-
104
- === GEM Installation
105
-
106
- Download the GEM file and install it with ..
107
-
108
- gem -i stream-VERSION.gem
109
-
110
- Use the correct version number for VERSION (e.g. 0.5). You may need
111
- root privileges to install.
112
-
113
- == See also
114
-
115
- * Streams in Smalltalk: http://wiki.cs.uiuc.edu/PatternStories/FunWithStreams
116
- * Simon Strandgaards iterator.rb[http://aeditor.rubyforge.org/iterator/files/iterator_rb.html]
117
-
118
- == Examples
119
-
120
- g = ('a'..'f').create_stream
121
- h = (1..10).create_stream
122
- i = (10..20).create_stream
123
-
124
- until g.at_end? || h.at_end? || i.at_end?
125
- p [g.forward, h.forward, i.forward]
126
- end
127
-
128
- def filestream fname
129
- Stream::ImplicitStream.new { |s|
130
- f = open(fname)
131
- s.at_end_proc = proc {f.eof?}
132
- s.forward_proc = proc {f.readline}
133
- # Need not implement backward moving to use the framework
134
- }
135
- end
136
-
137
- (filestream("/etc/passwd") + ('a'..'f').create_stream + filestream("/etc/group")).each do |l|
138
- puts l
139
- end
140
-
141
- puts "\nTwo filtered collection streams concatenated and reversed:\n\n"
142
-
143
- def newstream; (1..6).create_stream; end
144
- s = newstream.filtered { |x| x % 2 == 0 } + newstream.filtered { |x| x % 2 != 0 }
145
- s = s.reverse
146
- puts "Contents : #{s.to_a.join ' '}"
147
- puts "At end? : #{s.at_end?}"
148
- puts "At beginning? : #{s.at_beginning?}"
149
- puts "2xBackwards : #{s.backward} #{s.backward}"
150
- puts "Forward : #{s.forward}"
151
- puts "Peek : #{s.peek}"
152
- puts "Current : #{s.current}"
153
- puts "set_to_begin : Peek=#{s.set_to_begin;s.peek}"
154
-
155
- # an infinite stream (do not use set_to_end!)
156
- def randomStream
157
- Stream::ImplicitStream.new { |s|
158
- s.set_to_begin_proc = proc {srand 1234}
159
- s.at_end_proc = proc {false}
160
- s.forward_proc = proc {rand}
161
- }
162
- end
163
- s = randomStream.filtered { |x| x >= 0.5 }.collect { |x| sprintf("%5.2f ",x*100) }
164
- puts "5 random numbers: #{(1..5).collect {|x| s.forward}}\n" # =>
165
-
166
- 5 random numbers: 74.05 94.80 87.87 86.07 83.70
167
-
168
- == Other Stuff
169
-
170
- Author:: Horst Duchene
171
- License:: Copyright (c) 2001, 2013, 2016, 2020 Horst Duchene
172
- Released under the same license as Ruby