Module: Stream

Includes:
Enumerable
Included in:
Generator, BasicStream
Defined in:
lib/stream.rb

Overview

Module Stream defines an interface for an external Iterator which can move forward and backwards. See README for more information.

The functionality is similar to Smalltalk’s ReadStream.

Defined Under Namespace

Classes: BasicStream, CollectionStream, ConcatenatedStream, EmptyStream, EndOfStreamException, FilteredStream, ImplicitStream, IntervalStream, MappedStream, ReversedStream, WrappedStream

Instance Method Summary collapse

Instance Method Details

#+(otherStream) ⇒ Object

Create a Stream::ConcatenatedStream by concatenatating the receiver and otherStream

(%w(a b c).create_stream + [4,5].create_stream).to_a ==> ["a", "b", "c", 4, 5]


537
538
539
# File 'lib/stream.rb', line 537

def + (otherStream)
	[self, otherStream].create_stream.concatenate
end

#at_beginning?Boolean

Returns false if the next #backward will return an element.

Returns:

  • (Boolean)

Raises:

  • (NotImplementedError)


20
# File 'lib/stream.rb', line 20

def at_beginning?; raise NotImplementedError; end

#at_end?Boolean

Returns false if the next #forward will return an element.

Returns:

  • (Boolean)

Raises:

  • (NotImplementedError)


17
# File 'lib/stream.rb', line 17

def at_end?; raise NotImplementedError; end

#backwardObject

Move backward one position. Returns the source of current_edge. Raises Stream::EndOfStreamException if at_beginning? is true.



31
32
33
34
# File 'lib/stream.rb', line 31

def backward
  raise EndOfStreamException if at_beginning?
  basic_backward
end

#collect(&mapping) ⇒ Object

Create a Stream::MappedStream wrapper on self. Instead of returning the stream element on each move, the value of calling mapping is returned instead. See Stream::MappedStream for examples.



520
# File 'lib/stream.rb', line 520

def collect (&mapping); MappedStream.new(self, &mapping); end

#concatenateObject

Create a Stream::ConcatenatedStream on self, which must be a stream of streams.



523
# File 'lib/stream.rb', line 523

def concatenate; ConcatenatedStream.new self; end

#concatenate_collected(&mapping) ⇒ Object

Create a Stream::ConcatenatedStream, concatenated from streams build with the block for each element of self:

s = [1, 2, 3].create_stream.concatenate_collected { |i|
  [i,-i].create_stream
}.
s.to_a ==> [1, -1, 2, -2, 3, -3]


532
# File 'lib/stream.rb', line 532

def concatenate_collected (&mapping); self.collect(&mapping).concatenate; end

#create_streamObject

create_stream is used for each Enumerable to create a stream for it. A Stream as an Enumerable returns itself.



116
# File 'lib/stream.rb', line 116

def create_stream; self end

#currentObject

Returns the element returned by the last call of #forward. If at_beginning? is true self is returned.



84
# File 'lib/stream.rb', line 84

def current; at_beginning? ? self : basic_current; end

#current_edgeObject

Returns the array [#current,#peek].



91
# File 'lib/stream.rb', line 91

def current_edge; [current,peek]; end

#eachObject

Implements the standard iterator used by module Enumerable, by calling set_to_begin and basic_forward until at_end? is true.



107
108
109
110
111
112
# File 'lib/stream.rb', line 107

def each
  set_to_begin
  until at_end?
    yield basic_forward
  end
end

#empty?Boolean

Returns true if the stream is empty which is equivalent to at_end? and at_beginning? both being true.

Returns:

  • (Boolean)


103
# File 'lib/stream.rb', line 103

def empty?; at_end? and at_beginning?; end

#filtered(&block) ⇒ Object

Return a Stream::FilteredStream which iterates over all my elements satisfying the condition specified by the block.



512
# File 'lib/stream.rb', line 512

def filtered (&block); FilteredStream.new(self,&block); end

#firstObject

Returns the first element of the stream. This is accomplished by calling set_to_begin and #forward, which means a state change.



95
# File 'lib/stream.rb', line 95

def first; set_to_begin; forward; end

#forwardObject

Move forward one position. Returns the target of current_edge. Raises Stream::EndOfStreamException if at_end? is true.



24
25
26
27
# File 'lib/stream.rb', line 24

def forward
  raise EndOfStreamException if at_end?
  basic_forward
end

#lastObject

Returns the last element of the stream. This is accomplished by calling set_to_begin and #backward, which means a state change.



99
# File 'lib/stream.rb', line 99

def last; set_to_end; backward; end

#modify(&block) ⇒ Object

Create a Stream::ImplicitStream which wraps the receiver stream by modifying one or more basic methods of the receiver. As an example the method remove_first uses #modify to create an ImplicitStream which filters the first element away.



544
# File 'lib/stream.rb', line 544

def modify (&block); ImplicitStream.new(self, &block); end

#move_backward_untilObject

Move backward until the boolean block is not false and returns the element found. Returns nil if no object matches.



74
75
76
77
78
79
80
# File 'lib/stream.rb', line 74

def move_backward_until
	until at_beginning?
 element = basic_backward
 return element if yield(element)
	end
	nil
end

#move_forward_untilObject

Move forward until the boolean block is not false and returns the element found. Returns nil if no object matches.

This is similar to #detect, but starts the search from the current position. #detect, which is inherited from Enumerable uses #each, which implicitly calls #set_to_begin.



64
65
66
67
68
69
70
# File 'lib/stream.rb', line 64

def move_forward_until
	until at_end?
 element = basic_forward
 return element if yield(element)
	end
	nil
end

#peekObject

Returns the element returned by the last call of #backward. If at_end? is true self is returned.



88
# File 'lib/stream.rb', line 88

def peek; at_end? ? self : basic_peek; end

#remove_firstObject

Returns a Stream::ImplicitStream wrapping a Stream::FilteredStream, which eliminates the first element of the receiver.

(1..3).create_stream.remove_first.to_a ==> [2,3]


550
551
552
553
554
555
556
# File 'lib/stream.rb', line 550

def remove_first
	i = 0
	filter = self.filtered { | element | i += 1; i > 1 }
	filter.modify { |s|
 s.set_to_begin_proc = proc {filter.set_to_begin; i = 0}
	}
end

#remove_lastObject

Returns a Stream which eliminates the first element of the receiver.

(1..3).create_stream.remove_last.to_a ==> [1,2]

Take a look at the source. The implementation is inefficient but elegant.



563
564
565
# File 'lib/stream.rb', line 563

def remove_last
	self.reverse.remove_first.reverse	# I like this one
end

#reverseObject

Create a Stream::ReversedStream wrapper on self.



515
# File 'lib/stream.rb', line 515

def reverse; ReversedStream.new self; end

#set_to_beginObject

Position the stream before its first element, i.e. the next #forward will return the first element.



38
39
40
# File 'lib/stream.rb', line 38

def set_to_begin
  until at_beginning?; basic_backward; end
end

#set_to_endObject

Position the stream behind its last element, i.e. the next #backward will return the last element.



44
45
46
# File 'lib/stream.rb', line 44

def set_to_end
  until at_end?; basic_forward; end
end

#unwrappedObject

A Stream::WrappedStream should return the wrapped stream unwrapped. If the stream is not a wrapper around another stream it simply returns itself.



120
# File 'lib/stream.rb', line 120

def unwrapped; self; end