Ninju-streams 1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README ADDED
@@ -0,0 +1,23 @@
1
+ == Description
2
+
3
+ Streams is designed to be a lightweight streams processing library written in Ruby. I intend to keep this very small (infact, it's unlikely to change at all), and have added most common methods to make it immediately useable.
4
+
5
+ == Example
6
+
7
+ require 'streams'
8
+
9
+ class Stream
10
+ def sieve
11
+ Stream.new( head ) { tail.select { | n | n % head > 0 }.sieve }
12
+ end
13
+ end
14
+
15
+ module Math
16
+ PRIMES = 2.enumerate.sieve
17
+ end
18
+
19
+ >> Math::PRIMES.at( 30 )
20
+ => 127
21
+
22
+ >> Math::PRIMES.select { | n | n > 100 }.take( 50 )
23
+ => [101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379]
@@ -0,0 +1,32 @@
1
+ require "rubygems"
2
+ require "rake"
3
+ require "echoe"
4
+
5
+ Echoe.new( "streams", "1.0" ) do | p |
6
+ p.description = ""
7
+ p.url = "http://github.com/Ninju/streams"
8
+ p.author = "Alex Watt"
9
+ p.email = "alex.watt@me.com"
10
+ p.ignore_pattern = []
11
+ p.development_dependencies = []
12
+ end
13
+
14
+ task :default => "spec:run"
15
+
16
+
17
+ namespace :spec do
18
+ task :run do
19
+ system( "spec spec/" )
20
+ end
21
+
22
+ task :doc do
23
+ system( "spec spec/ --format specdoc" )
24
+ end
25
+
26
+ task :coverage do
27
+ system( "rcov spec/*_spec.rb" )
28
+ system( "open coverage/index.html" )
29
+ end
30
+ end
31
+
32
+ task :spec => "spec:run"
@@ -0,0 +1,156 @@
1
+ class Stream
2
+ attr_reader :head, :delayed_tail
3
+
4
+ def initialize( head = nil, &block )
5
+ @head = head
6
+ @delayed_tail = block || head && Proc.new { Stream.new }
7
+ end
8
+
9
+ def tail
10
+ @tail ||= delayed_tail && delayed_tail.call
11
+ end
12
+
13
+ def empty?
14
+ head.nil?
15
+ end
16
+
17
+ def size
18
+ return 0 if empty?
19
+ 1 + tail.size
20
+ end
21
+
22
+ def each( &block )
23
+ return if empty?
24
+ block.call( head )
25
+ tail.each( &block )
26
+ end
27
+
28
+ def map( &block )
29
+ return self if empty?
30
+ Stream.new( block.call( head ) ) { tail.map( &block ) }
31
+ end
32
+
33
+ def select( &block )
34
+ return self if empty?
35
+
36
+ if block.call( head )
37
+ return Stream.new( head ) { tail.select( &block ) }
38
+ end
39
+
40
+ tail.select( &block )
41
+ end
42
+
43
+ def reject( &block )
44
+ select do | element |
45
+ !block.call( element )
46
+ end
47
+ end
48
+
49
+ def merge( other )
50
+ return self if other.empty?
51
+ return other if self.empty?
52
+ Stream.new( head + other.head ) { tail.merge( other.tail ) }
53
+ end
54
+
55
+ def append( other )
56
+ return self if other.empty?
57
+ return other if empty?
58
+ Stream.new( head ) { tail.append( other ) }
59
+ end
60
+
61
+ def take( n )
62
+ return Stream.new if empty? || n.zero?
63
+ return Stream.new( head ) if n == 1
64
+ Stream.new( head ) { tail.take( n - 1 ) }
65
+ end
66
+
67
+ def at( n )
68
+ raise ArgumentError, "Index out of bounds" if empty? && n >= 0
69
+ return head if n.zero?
70
+ tail.at( n - 1 )
71
+ end
72
+
73
+ def drop( n )
74
+ return self if n.zero?
75
+ return Stream.new if empty?
76
+ tail.drop( n - 1 )
77
+ end
78
+
79
+ def uniq
80
+ return self if empty?
81
+ Stream.new( head ) { tail.select { | element | element != head }.uniq }
82
+ end
83
+
84
+ def last
85
+ return nil if empty?
86
+ return head if tail.empty?
87
+ tail.last
88
+ end
89
+
90
+ def to_a
91
+ return [] if empty?
92
+ [ head ] + tail.to_a
93
+ end
94
+
95
+ def join( separator = "" )
96
+ return "" if empty?
97
+ return head.to_s if tail.empty?
98
+ head.to_s + separator + tail.join( separator )
99
+ end
100
+
101
+ def inspect
102
+ "[" + join( ", " ) + "]"
103
+ end
104
+
105
+ def include?( element )
106
+ return false if empty?
107
+ head == element || tail.include?( element )
108
+ end
109
+
110
+ def ==( other )
111
+ head == other.head && tail == other.tail
112
+ end
113
+
114
+ def take_while( &block )
115
+ if block.call( head )
116
+ Stream.new( head ) { tail.take_while( &block ) }
117
+ else
118
+ Stream.new
119
+ end
120
+ end
121
+
122
+ def all?( &block )
123
+ return true if empty?
124
+ block.call( head ) && tail.all?( &block )
125
+ end
126
+
127
+ def any?( &block )
128
+ return false if empty?
129
+ block.call( head ) || tail.any?( &block )
130
+ end
131
+ end
132
+
133
+ class Array
134
+ def to_stream
135
+ return Stream.new if empty?
136
+ Stream.new( first ) { self[ 1..-1 ].to_stream }
137
+ end
138
+ end
139
+
140
+ class Integer
141
+ def enumerate( step = 1, &block )
142
+ if block_given?
143
+ return Stream.new( self ) { block.call( self ).enumerate( &block ) }
144
+ end
145
+ Stream.new( self ) { ( self + step ).enumerate( step ) }
146
+ end
147
+
148
+ def enumerate_to( value, step = 1, &block )
149
+ return Stream.new if ( step >= 0 && self > value ) || ( step < 0 && self < value )
150
+ if block_given?
151
+ return Stream.new( self ) { block.call( self ).enumerate_to( value, &block ) }
152
+ end
153
+
154
+ Stream.new( self ) { ( self + step ).enumerate_to( value, step ) }
155
+ end
156
+ end
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+ require 'mocha'
4
+
5
+ Spec::Runner.configure do |config|
6
+ config.mock_with :mocha
7
+ end
@@ -0,0 +1,430 @@
1
+ require File.join( File.dirname(__FILE__), *%w[spec_helper] )
2
+ require 'streams'
3
+
4
+ describe Stream do
5
+ it "should create a new instance" do
6
+ Proc.new { Stream.new }.should_not raise_error
7
+ end
8
+
9
+ describe "basic" do
10
+ before do
11
+ @empty_stream = Stream.new
12
+ @stream = Stream.new( 43 ) { @empty_stream }
13
+ end
14
+
15
+ it "should return the head" do
16
+ @stream.head.should == 43
17
+ end
18
+
19
+ it "should return the tail" do
20
+ @stream.tail.should == @empty_stream
21
+ end
22
+
23
+ it "should call the delayed tail" do
24
+ @stream.delayed_tail.expects( :call ).once.returns( @empty_stream )
25
+ @stream.tail
26
+ end
27
+
28
+ it "should store the delayed tail in a block" do
29
+ @stream.delayed_tail.is_a?( Proc ).should be_true
30
+ end
31
+
32
+ it "should not be empty" do
33
+ @stream.should_not be_empty
34
+ end
35
+
36
+ it "should have the correct size" do
37
+ @stream.size.should == 1 + @stream.tail.size
38
+ end
39
+ end
40
+
41
+ describe "stream with head and without tail" do
42
+ before do
43
+ @stream = Stream.new( 42 )
44
+ end
45
+
46
+ it "should return the empty stream" do
47
+ @stream.tail.should be_empty
48
+ end
49
+
50
+ it "should return a stream" do
51
+ @stream.tail.is_a?( Stream ).should be_true
52
+ end
53
+ end
54
+
55
+ describe "the empty stream" do
56
+ before do
57
+ @empty_stream = Stream.new
58
+ end
59
+
60
+ it "should be empty" do
61
+ @empty_stream.should be_empty
62
+ end
63
+
64
+ it "should have zero size" do
65
+ @empty_stream.size.should == 0
66
+ end
67
+
68
+ it "should return nil if you access the tail" do
69
+ @empty_stream.tail.should be_nil
70
+ end
71
+ end
72
+
73
+ describe "infinite stream" do
74
+ before do
75
+ @stream = Stream.new( 1 ) { @stream }
76
+ end
77
+
78
+ it "should return itself" do
79
+ @stream.stubs( :inspect ).returns( nil )
80
+ @stream.tail.should === @stream
81
+ end
82
+ end
83
+
84
+ describe "basic stream behaviour: " do
85
+ before do
86
+ @stream = Stream.new( 1 ) { Stream.new( 2 ) { Stream.new( 3 ) } }
87
+ end
88
+
89
+ describe "Stream#each" do
90
+ it "should loop through each element" do
91
+ array = []
92
+ @stream.each do | element |
93
+ array << element
94
+ end
95
+
96
+ @stream.to_a.should == array
97
+ end
98
+ end
99
+
100
+ describe "Stream#map" do
101
+ it "should add 1 to each element" do
102
+ add_one = Proc.new { | n | n + 1 }
103
+ new_stream = @stream.map( &add_one )
104
+
105
+ new_stream.head.should == add_one.call( @stream.head )
106
+ new_stream.tail.should == @stream.tail.map( &add_one )
107
+ end
108
+ end
109
+
110
+ describe "Stream#select" do
111
+ it "should select elements that return true when the predicate is applied to the element" do
112
+ even = Proc.new { | n | ( n % 2 ).zero? }
113
+
114
+ odd_starting_stream = @stream
115
+ odd_starting_filtered_stream = odd_starting_stream.select( &even )
116
+
117
+ odd_starting_filtered_stream.head.should_not == odd_starting_stream.head
118
+ odd_starting_filtered_stream.should == odd_starting_stream.tail.select( &even )
119
+
120
+ even_starting_stream = Stream.new( 0 ) { odd_starting_stream }
121
+ even_starting_filtered_stream = even_starting_stream.select( &even )
122
+
123
+ even_starting_filtered_stream.head.should == even_starting_stream.head
124
+ even_starting_filtered_stream.tail.should == even_starting_stream.tail.select( &even )
125
+ end
126
+ end
127
+
128
+ describe "Stream#take" do
129
+ it "should return a stream composed of the first N elements" do
130
+ first_two = @stream.take( 2 )
131
+ first_two.head.should == @stream.head
132
+ first_two.tail.should == @stream.tail.take( 1 )
133
+ end
134
+
135
+ it "should return an empty stream if the stream is empty" do
136
+ Stream.new.take( 100 ).should == Stream.new
137
+ end
138
+
139
+ it "should return the empty stream is N is zero" do
140
+ @stream.take( 0 ).should == Stream.new
141
+ end
142
+ end
143
+
144
+ describe "Stream#at" do
145
+ it "should raise an ArgumentError if the index is out of bounds" do
146
+ Proc.new { Stream.new.at( 50 ) }.should raise_error( ArgumentError )
147
+ end
148
+
149
+ it "should raise an ArgumentError if there are no elements in the stream" do
150
+ Proc.new { Stream.new.at( 0 ) }.should raise_error( ArgumentError )
151
+ end
152
+
153
+ it "should return the element at the Nth position" do
154
+ @stream.at( 1 ).should == 2
155
+ end
156
+ end
157
+
158
+ describe "Stream#drop" do
159
+ it "should remove the first n elements from the array" do
160
+ @stream.drop( 1 ).should == @stream.tail
161
+ end
162
+
163
+ it "should return the empty stream if the amount of elements to drop is greater than the size of the stream" do
164
+ Stream.new.drop( 1 ).should == Stream.new
165
+ end
166
+ end
167
+
168
+ describe "Stream#last" do
169
+ it "should return the last element" do
170
+ @stream.last.should == 3
171
+ end
172
+
173
+ it "should return nil if the stream is empty" do
174
+ Stream.new.last.should be_nil
175
+ end
176
+ end
177
+
178
+ describe "Stream#uniq" do
179
+ before do
180
+ @stream = Stream.new( 1 ) { Stream.new( 2 ) { Stream.new( 2 ) { Stream.new( 1 ) } } }
181
+ end
182
+
183
+ it "should remove duplicate elements" do
184
+ @stream.uniq.should == Stream.new( 1 ) { Stream.new( 2 ) }
185
+ end
186
+ end
187
+
188
+ describe "Stream#==(other)" do
189
+ before do
190
+ @other_stream = @stream.dup
191
+ end
192
+
193
+ it "should return false if the elements are different" do
194
+ Stream.new.should_not == @stream
195
+ end
196
+
197
+ it "should return true if they have the same elements" do
198
+ @stream.should == @other_stream
199
+ end
200
+ end
201
+
202
+ describe "Stream#reject" do
203
+ it "should remove elements which return true when the predicate is applied to the element" do
204
+ even = Proc.new { | n | ( n % 2 ).zero? }
205
+ odd_starting_stream = @stream
206
+ even_starting_stream = Stream.new( 0 ) { odd_starting_stream }
207
+
208
+ even_starting_filtered_stream = even_starting_stream.reject( &even )
209
+ even_starting_filtered_stream.head.should_not == even_starting_stream.head
210
+ even_starting_filtered_stream.should == even_starting_stream.tail.reject( &even )
211
+
212
+ odd_starting_filtered_stream = odd_starting_stream.reject( &even )
213
+ odd_starting_filtered_stream.head.should == odd_starting_stream.head
214
+ odd_starting_filtered_stream.tail.should == odd_starting_stream.tail.reject( &even )
215
+ end
216
+ end
217
+
218
+ describe "Stream#merge" do
219
+ before do
220
+ @ones = Stream.new( 1 ) { Stream.new( 1 ) }
221
+ @twos = Stream.new( 2 ) { Stream.new( 2 ) }
222
+ end
223
+
224
+ it "should merge the streams by summing each pairing element and constructing a new stream" do
225
+ threes = @ones.merge( @twos )
226
+ threes.head.should == @ones.head + @twos.head
227
+
228
+ threes.tail.should == @ones.tail.merge( @twos.tail )
229
+ end
230
+
231
+ it "should return the mergee if the merger is empty" do
232
+ Stream.new.merge( @ones ).should == @ones
233
+ end
234
+
235
+ it "should return the merger if the mergee is empty" do
236
+ @ones.merge( Stream.new ).should == @ones
237
+ end
238
+ end
239
+
240
+ describe "Stream#take_while( &block )" do
241
+ it "should return a stream of the elements to the point where block.call( element ) is false" do
242
+ @stream.take_while { | n | n == 1 }.should == Stream.new( 1 )
243
+ end
244
+ end
245
+
246
+ describe "Stream#append" do
247
+ before do
248
+ @ones = Stream.new( 1 ) { Stream.new( 1 ) }
249
+ @twos = Stream.new( 2 ) { Stream.new( 2 ) }
250
+ end
251
+
252
+ it "should append the streams" do
253
+ appended_stream = @ones.append( @twos )
254
+ appended_stream.head.should == @ones.head
255
+ appended_stream.tail.should == @ones.tail.append( @twos )
256
+ end
257
+
258
+ it "should return the appendee if the appender is empty" do
259
+ Stream.new.append( @ones ).should == @ones
260
+ end
261
+
262
+ it "should return the appender if the appendee is empty" do
263
+ @ones.append( Stream.new ).should == @ones
264
+ end
265
+ end
266
+
267
+ describe "Stream#include?" do
268
+ it "should return false if the object is not an element in the stream" do
269
+ Stream.new.should_not include( "Hello, world!" )
270
+ end
271
+
272
+ it "should return true if the object is an element in the stream" do
273
+ @stream.should include( 1 )
274
+ end
275
+ end
276
+
277
+ describe "Stream#to_a" do
278
+ it "should return the elements of the stream as an array" do
279
+ @stream.to_a.should == [ 1, 2, 3 ]
280
+ end
281
+
282
+ it "should return an empty array if the stream is empty" do
283
+ Stream.new.to_a.should == []
284
+ end
285
+ end
286
+
287
+ describe "Stream#join" do
288
+ it "should be an empty string if the stream is empty" do
289
+ Stream.new.join.should == ""
290
+ end
291
+
292
+ it "should print the head as a string if there is only one element" do
293
+ Stream.new( 1 ).join.should == 1.to_s
294
+ end
295
+
296
+ it "should join the elements by the separator" do
297
+ @stream.join( ", " ).should == "1, 2, 3"
298
+ end
299
+ end
300
+
301
+ describe "Stream#any?( &block )" do
302
+ it "should return false if the stream is empty" do
303
+ Stream.new.any? { | n | true }.should be_false
304
+ end
305
+
306
+ it "should return true if any of the elements return true when passed to the block" do
307
+ @stream.any? { | n | n == 2 }.should be_true
308
+ end
309
+
310
+ it "should return false if none of the elements return true when passed to the block" do
311
+ @stream.any? { | n | n < -500 }.should be_false
312
+ end
313
+ end
314
+
315
+ describe "Stream#all?( &block )" do
316
+ it "should return true if the stream is empty" do
317
+ Stream.new.all? { | element | false }.should be_true
318
+ end
319
+
320
+ it "should return true if all the elements return true when the block is applied to the element" do
321
+ @stream.all? { | n | n > 0 }.should be_true
322
+ end
323
+
324
+ it "should return false if any of the elements return false when the block is applied to the element" do
325
+ @stream.all? { | n | n != 2 }.should be_false
326
+ end
327
+ end
328
+
329
+ describe "Stream#inspect" do
330
+ it "should show [].to_s if the stream is empty" do
331
+ Stream.new.inspect.should == "[]"
332
+ end
333
+
334
+ it "should show the elements in an array - stream.to_s.inspect" do
335
+ @stream.inspect.should == "[1, 2, 3]"
336
+ end
337
+ end
338
+
339
+ it "should cache the tail" do
340
+ @stream.delayed_tail.expects( :call ).with.once.returns( @stream )
341
+ 2.times { @stream.tail }
342
+ end
343
+ end
344
+ end
345
+
346
+ describe Array, "Stream helpers" do
347
+ before do
348
+ @array = [ 1, 2, 3 ]
349
+ end
350
+
351
+ describe "Array#to_stream" do
352
+ it "should convert the array to a stream" do
353
+ @array.to_stream.should be_kind_of( Stream )
354
+ end
355
+
356
+ it "should fill the stream with the correct elements" do
357
+ stream = @array.to_stream
358
+ @array.first.should == stream.head
359
+ @array[ 1..-1 ].to_stream.should == stream.tail
360
+ end
361
+
362
+ it "should return an empty stream if the array is empty" do
363
+ [].to_stream.should == Stream.new
364
+ end
365
+ end
366
+ end
367
+
368
+ describe Integer, "Stream helpers" do
369
+ describe "Integer#enumerate( step = 1, &block )" do
370
+ it "should create an infinite stream of the natural numbers" do
371
+ natural_numbers = 0.enumerate
372
+ natural_numbers.head.should == 0
373
+ natural_numbers.tail.head.should == 1
374
+ natural_numbers.at( 30 ).should == 30
375
+ end
376
+
377
+ it "should return a stream" do
378
+ 2.enumerate.should be_kind_of( Stream )
379
+ end
380
+
381
+ it "should create an infinite stream with the difference between each element being the step passed" do
382
+ multiples_of_5 = 0.enumerate( 5 )
383
+ multiples_of_5.head.should == 0
384
+ multiples_of_5.at( 5 ).should == 25
385
+ multiples_of_5.at( 10 ).should == 50
386
+ end
387
+
388
+ it "should create an infinite stream with the difference between element being the difference between the proc applied to each element" do
389
+ powers_of_2 = 1.enumerate { | n | n * 2 }
390
+ powers_of_2.head.should == 1
391
+ powers_of_2.at( 2 ).should == 4
392
+ powers_of_2.at( 4 ).should == 16
393
+ end
394
+
395
+ it "should generate the next number based on the block rather than the step" do
396
+ multiples_of_10 = 0.enumerate( 5 ) { | n | n + 10 }
397
+ multiples_of_10.at( 0 ).should == 0
398
+ multiples_of_10.at( 1 ).should == 10
399
+ multiples_of_10.at( 2 ).should == 20
400
+ end
401
+ end
402
+
403
+ describe "Integer#enumerate_to( value, step = 1, &block )" do
404
+ it "should return a stream" do
405
+ 0.enumerate_to( 100 ).should be_kind_of( Stream )
406
+ end
407
+
408
+ it "should not contain an element less than value if the step is negative" do
409
+ 100.enumerate_to( 0, -3 ).any? { | n | n < 0 }.should_not be_true
410
+ end
411
+
412
+ it "should not contain an element greater than value if the step is positive" do
413
+ 0.enumerate_to( 100, 3 ).any? { | n | n > 100 }.should_not be_true
414
+ end
415
+
416
+ it "should generate the next number based on the block rather than the step" do
417
+ stream = 0.enumerate_to( 100, 3 ) { | n | n + 11 }
418
+ stream.head.should == 0
419
+ stream.at( 1 ).should == 11
420
+ stream.at( 2 ).should == 22
421
+ end
422
+
423
+ it "should generate the next number based on the proc passed" do
424
+ stream = 0.enumerate_to( 100 ) { | n | n + 11 }
425
+ stream.head == 0
426
+ stream.at( 1 ).should == 11
427
+ stream.at( 2 ).should == 22
428
+ end
429
+ end
430
+ end
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{streams}
5
+ s.version = "1.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Alex Watt"]
9
+ s.date = %q{2009-02-12}
10
+ s.description = %q{}
11
+ s.email = %q{alex.watt@me.com}
12
+ s.extra_rdoc_files = ["lib/streams.rb", "README"]
13
+ s.files = ["lib/streams.rb", "Rakefile", "README", "spec/spec_helper.rb", "spec/streams_spec.rb", "Manifest", "streams.gemspec"]
14
+ s.has_rdoc = true
15
+ s.homepage = %q{http://github.com/Ninju/streams}
16
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Streams", "--main", "README"]
17
+ s.require_paths = ["lib"]
18
+ s.rubyforge_project = %q{streams}
19
+ s.rubygems_version = %q{1.3.1}
20
+ s.summary = %q{}
21
+
22
+ if s.respond_to? :specification_version then
23
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
24
+ s.specification_version = 2
25
+
26
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
27
+ else
28
+ end
29
+ else
30
+ end
31
+ end
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: Ninju-streams
3
+ version: !ruby/object:Gem::Version
4
+ version: "1.0"
5
+ platform: ruby
6
+ authors:
7
+ - Alex Watt
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-02-12 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: ""
17
+ email: alex.watt@me.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - lib/streams.rb
24
+ - README
25
+ files:
26
+ - lib/streams.rb
27
+ - Rakefile
28
+ - README
29
+ - spec/spec_helper.rb
30
+ - spec/streams_spec.rb
31
+ - Manifest
32
+ - streams.gemspec
33
+ has_rdoc: true
34
+ homepage: http://github.com/Ninju/streams
35
+ post_install_message:
36
+ rdoc_options:
37
+ - --line-numbers
38
+ - --inline-source
39
+ - --title
40
+ - Streams
41
+ - --main
42
+ - README
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: "0"
50
+ version:
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "1.2"
56
+ version:
57
+ requirements: []
58
+
59
+ rubyforge_project: streams
60
+ rubygems_version: 1.2.0
61
+ signing_key:
62
+ specification_version: 2
63
+ summary: ""
64
+ test_files: []
65
+