Class: Transformer
Overview
A class implementing transformer coroutines
A Transformer can be created by the following methods:
-
Object#trans_for
-
Transformer.new
Transformers are pieces of code that accept input values and produce output values (without returning from their execution context like in a regular method call). They are used by connecting either their input to an enumerable or their output to a sink (or both, using Sink#<= or Enumerable#>=). An enumerable is any object implementing an iterator method each; a sink is any object implementing the << operator (which is assumed to store or output the supplied values in some form).
The input of a transformer is connected to an enumerable enum
using trans <= enum, the result of which is a new Enumerator instance. The transformer is started upon iterating over this Enumerator. Whenever the transformer requests a new input value (see Object#trans_for and Transformer#new for how to do this), iteration over enum
is resumed. The output values of the transformer (again, see Object#trans_for and Transformer#new) are yielded by the enclosing Enumerator. When enum
is exhausted, StopIteration is raised at the point where the transformer last requested an input value. It is expected that the transformer will then terminate without requesting any more values (though it may execute e.g. some cleanup actions).
The output of a transformer is connected to a sink using trans >= sink, the result of which is a new Consumer instance. The transformer starts executing right away; when it requests its first input value, the >= operation returns. Input values supplied using << to the enclosing Consumer are forwarded to the transformer by resuming execution at the point where it last requested an input value. Output values produced by the transformer are fed to sink#<<. After terminating, the result of the new Consumer is the value returned by sink.close (see Consumer#result and Consumer#close).
Transformers can also be chained together by connecting the output of one the input the next using trans >= other_trans or trans <= other_trans. See Transformer#>= and Transformer#<= for details.
Defined Under Namespace
Classes: FirstYielder, SecondYielder
Instance Method Summary collapse
-
#<=(source) ⇒ Object
:call-seq: trans <= other_trans -> new_trans trans <= enum -> new_enum.
-
#>=(sink) ⇒ Object
:call-seq: trans >= other_trans -> new_trans trans >= sink -> consum.
-
#initialize(&block) ⇒ Transformer
constructor
:call-seq: Transformer.new { |yielder| … } -> trans.
- #inspect ⇒ Object
-
#to_trans ⇒ Object
:call-seq: transformer.to_trans -> transformer.
Constructor Details
#initialize(&block) ⇒ Transformer
:call-seq:
Transformer.new { |yielder| ... } -> trans
Creates a new Transformer coroutine defined by the given block.
The block is called with a “yielder” object as parameter. yielder
can be used to retrieve a value from the consumption context by calling its await method (as in Consumer.new), and to yield a value by calling its yield method (as in Enumerator.new).
running_sum = Transformer.new do |y|
result = 0
loop { result += y.await; y.yield result }
end
(1..3) >= running_sum >= [] # => [1, 3, 6]
163 164 165 |
# File 'lib/coroutines/base.rb', line 163 def initialize(&block) @self = block end |
Instance Method Details
#<=(source) ⇒ Object
:call-seq:
trans <= other_trans -> new_trans
trans <= enum -> new_enum
In the first form, creates a new Transformer that has the input of trans
connected to the output of other_trans
.
In the second form, creates a new Enumerator by connecting enum
to the input of trans
. See Transformer for details.
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'lib/coroutines/base.rb', line 188 def <=(source) if not source.respond_to? :each return source.to_trans.transformer_chain self end source_enum = source.to_enum enum = Enumerator.new do |y| y.define_singleton_method :await do source_enum.next end @self.call(y) end description = "#<Enumerator: #{inspect} <= #{source.inspect}>" enum.define_singleton_method :inspect do description end enum end |
#>=(sink) ⇒ Object
:call-seq:
trans >= other_trans -> new_trans
trans >= sink -> consum
In the first form, creates a new Transformer that has the output of trans
connected to the input of other_trans
.
In the second form, creates a new Consumer by connecting the output of trans
to sink
. See Transformer for details.
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
# File 'lib/coroutines/base.rb', line 218 def >=(sink) if not sink.respond_to? :<< return transformer_chain sink.to_trans end consum = Consumer.new do |y| y.define_singleton_method :yield do |args| sink << args end y.singleton_class.instance_eval { alias_method :<<, :yield } begin @self.call(y) rescue StopIteration end sink.close end description = "#<Consumer: #{inspect} >= #{sink.inspect}>" consum.define_singleton_method :inspect do description end consum end |
#inspect ⇒ Object
167 168 169 |
# File 'lib/coroutines/base.rb', line 167 def inspect "#<Transformer: 0x#{object_id.to_s(16)}>" end |
#to_trans ⇒ Object
:call-seq:
transformer.to_trans -> transformer
Returns self.
175 176 177 |
# File 'lib/coroutines/base.rb', line 175 def to_trans self end |