stream 0.5

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,174 @@
1
+ = Extended External Iterators (forward and backward)
2
+
3
+ == Description
4
+
5
+ Module Stream defines an interface for external iterators. A stream can be
6
+ seen as an iterator on a sequence of objects x1,...,xn. The state of the
7
+ stream is uniquely determined by the following methods:
8
+
9
+ * at_beginning?
10
+ * at_end?
11
+ * current
12
+ * peek
13
+
14
+ State changes are done with the following operations:
15
+
16
+ * set_to_begin
17
+ * set_to_end
18
+ * forward
19
+ * backward
20
+
21
+ With the help of the method current_edge the state of a stream s can be
22
+ exactly defined
23
+
24
+ s.current_edge == [s.current, s.peek]
25
+
26
+ If s a stream on [x1,...,xn]. Consider the edges [xi,xi+1] i=1,...,n and
27
+ [x0,x1] and [xn,xn+1] (x0 and xn are helper elements to define the boundary
28
+ conditions). Then if s is non empty, the following conditions must be true:
29
+
30
+ s.at_beginning? <=> s.current_edge == [x0,x1]
31
+ s.at_end? <=> s.current_edge == [xn,xn+1]
32
+ s.isEmpty? <=> s.at_beginning? && s.at_end? <=> s.current_edge == [x0,x1] <=> n = 0
33
+ s.set_to_end => s.at_end?
34
+ s.set_to_begin => s.at_beginning?
35
+
36
+ If 0 <= i < n and s.current_edge == [xi, xi+1] , then:
37
+
38
+ [s.forward, s.current_edge] == [xi+1, [xi+1, xi+2]]
39
+
40
+ If 1 <= i < n and s.current_edge == [xi, xi+1] , then:
41
+
42
+ [s.backward, s.current_edge] == [xi, [xi-1, xi]]
43
+
44
+ The result of peek is the same as of forward without changing state. The result of
45
+ current is the same as of backward without changing state.
46
+
47
+ Module Stream includes Enumerable implementing #each in the obvious way.
48
+
49
+ Not every stream needs to implement #backward and #at_beginning? thus being
50
+ not reversable. If they are reversable peek can easily be implemented using
51
+ forward and backward, as is done in module Stream. If a stream is not
52
+ reversable all derived streams provided by the stream module (filter,
53
+ mapping, concatenation) can be used anyway. Explicit or implicit (via peek or
54
+ current) uses of backward would throw a NotImplementedError.
55
+
56
+ Classes implementing the stream interface must implement the following methods:
57
+
58
+ * basic_forward
59
+ * basic_backward
60
+
61
+ * at_end?
62
+ * at_beginning?
63
+
64
+ The methods set_to_end and set_to_begin are by default implemented as:
65
+
66
+ set_to_end : until at_end?; do basic_forward end
67
+ set_to_begin : until at_beginning?; do basic_backward end
68
+
69
+ The methods forward and backward are by default implemented as:
70
+
71
+ forward: raise EndOfStreamException if at_end?; basic_forward.
72
+ backward: raise EndOfStreamException if at_beginning?; basic_backward
73
+
74
+ Thus subclasses must only implement *four* methods. Efficiency sometimes
75
+ demands better implementations.
76
+
77
+ There are several concrete classes implementing the stream interface:
78
+
79
+ * Stream::EmptyStream (boring)
80
+ * Stream::CollectionStream created by the method Array#create_stream
81
+ * Stream::FilteredStream created by the method Stream#filtered
82
+ * Stream::ReversedStream created by the method Stream#reverse
83
+ * Stream::ConcatenatedStream created by the method Stream#concatenate
84
+ * Stream::ImplicitStream using closures for the basic methods to implement
85
+
86
+ == Download
87
+
88
+ The latest version of stream.rb can be found at
89
+
90
+ * http://rubyforge.org/frs/?group_id=110
91
+
92
+ == Installation
93
+
94
+ === Normal Installation
95
+
96
+ You can install stream with the following command.
97
+
98
+ % ruby install.rb
99
+
100
+ from its distribution directory.
101
+
102
+ === GEM Installation
103
+
104
+ Download the GEM file and install it with ..
105
+
106
+ gem -i stream-VERSION.gem
107
+
108
+ Use the correct version number for VERSION (e.g. 0.5). You may need
109
+ root privileges to install.
110
+
111
+ == See also
112
+
113
+ * Streams in Smalltalk: http://wiki.cs.uiuc.edu/PatternStories/FunWithStreams
114
+ * Simon Strandgaards iterator.rb[http://aeditor.rubyforge.org/iterator/files/iterator_rb.html]
115
+ * IterationStyles: http://www.rubygarden.org/ruby?IterationStyles
116
+
117
+ == Examples
118
+
119
+ g = ('a'..'f').create_stream
120
+ h = (1..10).create_stream
121
+ i = (10..20).create_stream
122
+
123
+ until g.at_end? || h.at_end? || i.at_end?
124
+ p [g.forward, h.forward, i.forward]
125
+ end
126
+
127
+ def filestream fname
128
+ Stream::ImplicitStream.new { |s|
129
+ f = open(fname)
130
+ s.at_end_proc = proc {f.eof?}
131
+ s.forward_proc = proc {f.readline}
132
+ # Need not implement backward moving to use the framework
133
+ }
134
+ end
135
+
136
+ (filestream("/etc/passwd") + ('a'..'f').create_stream + filestream("/etc/group")).each do |l|
137
+ puts l
138
+ end
139
+
140
+ puts "\nTwo filtered collection streams concatenated and reversed:\n\n"
141
+
142
+ def newstream; (1..6).create_stream; end
143
+ s = newstream.filtered { |x| x % 2 == 0 } + newstream.filtered { |x| x % 2 != 0 }
144
+ s = s.reverse
145
+ puts "Contents : #{s.to_a.join ' '}"
146
+ puts "At end? : #{s.at_end?}"
147
+ puts "At beginning? : #{s.at_beginning?}"
148
+ puts "2xBackwards : #{s.backward} #{s.backward}"
149
+ puts "Forward : #{s.forward}"
150
+ puts "Peek : #{s.peek}"
151
+ puts "Current : #{s.current}"
152
+ puts "set_to_begin : Peek=#{s.set_to_begin;s.peek}"
153
+
154
+ # an infinite stream (do not use set_to_end!)
155
+ def randomStream
156
+ Stream::ImplicitStream.new { |s|
157
+ s.set_to_begin_proc = proc {srand 1234}
158
+ s.at_end_proc = proc {false}
159
+ s.forward_proc = proc {rand}
160
+ }
161
+ end
162
+ s = randomStream.filtered { |x| x >= 0.5 }.collect { |x| sprintf("%5.2f ",x*100) }
163
+ puts "5 random numbers: #{(1..5).collect {|x| s.forward}}\n" # =>
164
+
165
+ 5 random numbers: 74.05 94.80 87.87 86.07 83.70
166
+
167
+ == Other Stuff
168
+
169
+ $Revision: 1.1.1.1 $
170
+ $Date: 2004/05/13 23:30:03 $
171
+
172
+ Author:: Horst Duchene <hd.at.clr@hduchene.de>
173
+ License:: Copyright (c) 2001, 2004 Horst Duchene
174
+ Released under the same license as Ruby
@@ -0,0 +1,161 @@
1
+ # Rakefile for -*- ruby -*-
2
+
3
+ begin
4
+ require 'rubygems'
5
+ rescue Exception
6
+ nil
7
+ end
8
+ require 'rake/clean'
9
+ require 'rake/testtask'
10
+ require 'rake/gempackagetask'
11
+ require 'rake/rdoctask'
12
+
13
+ # Determine the current version of the software
14
+
15
+ if `ruby -Ilib -rstream -e'puts STREAM_VERSION'` =~ /\S+$/
16
+ PKG_VERSION = $&
17
+ else
18
+ PKG_VERSION = "0.0.0"
19
+ end
20
+
21
+ SRC_RB = FileList['lib/*.rb']
22
+
23
+ # The default task is run if rake is given no explicit arguments.
24
+
25
+ desc "Default Task"
26
+ task :default => :test
27
+
28
+ # Define a test task.
29
+
30
+ Rake::TestTask.new { |t|
31
+ #t.libs << "tests"
32
+ #t.pattern = 'tests/Test*.rb'
33
+ t.verbose = true
34
+ }
35
+
36
+ task :test
37
+
38
+ # Define a test that will run all the test targets.
39
+ desc "Run all test targets"
40
+ task :testall => [:test ]
41
+
42
+ # Install stream using the standard install.rb script.
43
+
44
+ desc "Install the application"
45
+ task :install do
46
+ ruby "install.rb"
47
+ end
48
+
49
+ # Create a task to build the RDOC documentation tree.
50
+
51
+ rd = Rake::RDocTask.new("rdoc") { |rdoc|
52
+ rdoc.rdoc_dir = 'html'
53
+ # rdoc.template = 'kilmer'
54
+ # rdoc.template = 'css2'
55
+ rdoc.title = "Stream - Extended External Iterators"
56
+ rdoc.options << '--line-numbers' << '--inline-source'
57
+ rdoc.rdoc_files.include('README')
58
+ rdoc.rdoc_files.include('lib/*.rb', 'doc/**/*.rdoc')
59
+ }
60
+
61
+ # ====================================================================
62
+ # Create a task that will package the stream software into distributable
63
+ # tar, zip and gem files.
64
+
65
+ PKG_FILES = FileList[
66
+ 'install.rb',
67
+ '[A-Z]*',
68
+ 'lib/**/*.rb',
69
+ 'test/**/*.rb',
70
+ 'examples/**/*'
71
+ ]
72
+
73
+ if ! defined?(Gem)
74
+ puts "Package Target requires RubyGEMs"
75
+ else
76
+ spec = Gem::Specification.new do |s|
77
+
78
+ #### Basic information.
79
+
80
+ s.name = 'stream'
81
+ s.version = PKG_VERSION
82
+ s.summary = "Stream - Extended External Iterators"
83
+ s.description = <<-EOF
84
+ Module Stream defines an interface for external iterators.
85
+ EOF
86
+
87
+ #### Dependencies and requirements.
88
+
89
+ #s.add_dependency('log4r', '> 1.0.4')
90
+ #s.requirements << ""
91
+
92
+ #### Which files are to be included in this gem? Everything! (Except CVS directories.)
93
+
94
+ s.files = PKG_FILES.to_a
95
+
96
+ #### C code extensions.
97
+
98
+ #s.extensions << "ext/rmagic/extconf.rb"
99
+
100
+ #### Load-time details: library and application (you will need one or both).
101
+
102
+ s.require_path = 'lib' # Use these for libraries.
103
+ s.autorequire = 'stream'
104
+
105
+ #### Documentation and testing.
106
+
107
+ s.has_rdoc = true
108
+ #s.test_suite_file = "test/rmagic-tests.rb"
109
+
110
+ #### Author and project details.
111
+ s.author = "Horst Duchene"
112
+ s.email = "hd.at.clr@hduchene.de"
113
+ s.homepage = "http://rgl.rubyforge.org"
114
+ s.rubyforge_project = "rgl"
115
+ end
116
+
117
+ Rake::GemPackageTask.new(spec) do |pkg|
118
+ pkg.need_zip = true
119
+ pkg.need_tar = true
120
+ end
121
+ end
122
+
123
+ # Misc tasks =========================================================
124
+
125
+ def count_lines(filename)
126
+ lines = 0
127
+ codelines = 0
128
+ open(filename) { |f|
129
+ f.each do |line|
130
+ lines += 1
131
+ next if line =~ /^\s*$/
132
+ next if line =~ /^\s*#/
133
+ codelines += 1
134
+ end
135
+ }
136
+ [lines, codelines]
137
+ end
138
+
139
+ def show_line(msg, lines, loc)
140
+ printf "%6s %6s %s\n", lines.to_s, loc.to_s, msg
141
+ end
142
+
143
+ desc "Count lines in the main files"
144
+ task :lines do
145
+ total_lines = 0
146
+ total_code = 0
147
+ show_line("File Name", "LINES", "LOC")
148
+ SRC_RB.each do |fn|
149
+ lines, codelines = count_lines(fn)
150
+ show_line(fn, lines, codelines)
151
+ total_lines += lines
152
+ total_code += codelines
153
+ end
154
+ show_line("TOTAL", total_lines, total_code)
155
+ end
156
+
157
+ ARCHIVEDIR = '/mnt/flash'
158
+
159
+ task :archive => [:package] do
160
+ cp FileList["pkg/*.tgz", "pkg/*.zip", "pkg/*.gem"], ARCHIVEDIR
161
+ end
@@ -0,0 +1,51 @@
1
+ require 'stream'
2
+
3
+ # Example from knu's Generator.rb
4
+ g = ('a'..'f').create_stream
5
+ h = (1..10).create_stream
6
+ i = (10..20).create_stream
7
+
8
+ until g.at_end? || h.at_end? || i.at_end?
9
+ p [g.forward, h.forward, i.forward]
10
+ end
11
+
12
+ puts "Concatenate Filestreams and collection stream:\n"
13
+
14
+ def fs fname
15
+ Stream::ImplicitStream.new { |s|
16
+ f = open(fname)
17
+ s.at_end_proc = proc {f.eof?}
18
+ s.forward_proc = proc {f.readline}
19
+ # Need not implement backward moving to use the framework
20
+ }
21
+ end
22
+
23
+ (fs("/etc/passwd") + ('a'..'f').create_stream + fs("/etc/group")).each do |l|
24
+ puts l
25
+ end
26
+
27
+ puts "\nTwo filtered collection streams concatenated and reversed:\n\n"
28
+
29
+ def newstream; (1..6).create_stream; end
30
+ s = newstream.filtered { |x| x % 2 == 0 } \
31
+ + newstream.filtered { |x| x % 2 != 0 }
32
+ s = s.reverse
33
+ puts "Contents : #{s.to_a.join ' '}"
34
+ puts "At end? : #{s.at_end?}"
35
+ puts "At beginning? : #{s.at_beginning?}"
36
+ puts "2xBackwards : #{s.backward} #{s.backward}"
37
+ puts "Forward : #{s.forward}"
38
+ puts "Peek : #{s.peek}"
39
+ puts "Current : #{s.current}"
40
+ puts "set_to_begin : Peek=#{s.set_to_begin;s.peek}"
41
+
42
+ # an infinite stream (do not use set_to_end!)
43
+ def randomStream
44
+ Stream::ImplicitStream.new { |s|
45
+ s.set_to_begin_proc = proc {srand 1234}
46
+ s.at_end_proc = proc {false}
47
+ s.forward_proc = proc {rand}
48
+ }
49
+ end
50
+ s = randomStream.filtered { |x| x >= 0.5 }.collect { |x| sprintf("%5.2f ",x*100) }
51
+ puts "5 random numbers: #{(1..5).collect {|x| s.forward}}\n"
@@ -0,0 +1,59 @@
1
+ #
2
+ # Simple stream test interface based on Ruby-FLTK
3
+ # See: (http://ruby-fltk.sourceforge.net/)
4
+ #
5
+ require 'fltk'
6
+ require 'stream'
7
+
8
+ class StreamTester < Fltk::Window
9
+ include Stream
10
+ def initialize (s)
11
+ super(200,200)
12
+ @stream = s
13
+
14
+ pack = Fltk::Pack.new(200,200) {
15
+ %w{set_to_begin set_to_end forward backward at_end? at_beginning? current_edge entries inspect}.each { |m|
16
+ Fltk::Button.new(50,20,m) {|w,data|
17
+ @output.value(sendMsg(m))
18
+ puts sendMsg(m)
19
+ }
20
+ }
21
+ @output= Fltk::Input.new(200, 20)
22
+ @output.deactivate
23
+ }
24
+ pack.packtype = Fltk::VERTICAL
25
+ self.add(pack)
26
+ self.show
27
+ end
28
+
29
+ def sendMsg(m)
30
+ begin
31
+ @stream.send(m).inspect
32
+ rescue EndOfStreamException => msg
33
+ msg
34
+ end
35
+ end
36
+ end
37
+
38
+ module Stream
39
+ def openTester
40
+ StreamTester.new(self)
41
+ Fltk::run()
42
+ end
43
+ end
44
+
45
+ if $0 == __FILE__
46
+ def newstream; (1..6).create_stream; end
47
+ s = newstream.filtered { |x| x % 2 == 0 } \
48
+ + newstream.filtered { |x| x % 2 != 0 }
49
+ s.reverse.openTester
50
+
51
+ # an infinite stream (do not use set_to_end!)
52
+ randomStream =
53
+ Stream::ImplicitStream.new { |s|
54
+ s.set_to_begin_proc = proc {srand 1234}
55
+ s.at_end_proc = proc {false}
56
+ s.forward_proc = proc {rand}
57
+ }
58
+ randomStream.filtered { |x| x >= 0.5 }.collect { |x| x*100 }.openTester
59
+ end
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rbconfig'
4
+ require 'ftools'
5
+ require 'find'
6
+
7
+ SRC_BASE = 'lib'
8
+ INSTDIR = File.join Config::CONFIG['sitedir']
9
+
10
+ def install
11
+ begin
12
+ pwd = Dir.pwd
13
+ Dir.chdir(SRC_BASE)
14
+ Dir['*.rb'].each do |file|
15
+ dst = File.join( INSTDIR, file )
16
+ File.install(file, dst, 0644, true)
17
+ end
18
+ Dir.chdir(pwd)
19
+ rescue
20
+ puts $!
21
+ end
22
+ end
23
+
24
+ install