class Object
Constants
- Multicast
convenience alias for
Sink::Multicast
(this is not defined when requiring just coroutines/base)
Public Instance Methods
Evaluates to the next input value from the associated consumption context. In order to create a consumption context, you have to use Object#consum_for
or Object#trans_for
on the method calling await.
The behavior of await is undefined if the method using it is called without being wrapped by consum_for
or trans_for. It should be an error to do so, as it is an error to use yield without an associated block; however, since await is not a language primitive (like yield), it is not always possible to enforce this. This is likely to change in a future version if a better solution can be found.
# File lib/coroutines.rb, line 123 def await yielder = Fiber.current.instance_variable_get(:@yielder) raise CoroutineError, "you can't call a consumer" if yielder.nil? yielder.await end
Creates a new Consumer
coroutine from the given method. This is analogous to using Kernel#enum_for to create an Enumerator
instance. The method is called immediately (with the given args
). It executes until the first call to await
, at which point consum_for
returns the Consumer
instance. Calling consumer << obj resumes the consumer at the point where it last executed await
, which evaluates to obj
.
Calling consumer.close raises StopIteration at the point where the consumer last executed await
; it is expected that it will terminate without executing await
again. Consumer#close
evaluates to the return value of the method.
Example:
def counter(start) result = start loop { result += await } "Final value: #{result}" end co = consum_for :counter, 10 #=> #<Consumer: main:counter (running)> co << 10 << 1000 << 10000 co.close #=> "Final value: 11020"
# File lib/coroutines.rb, line 158 def consum_for(meth, *args) cons = Consumer.new do |y| Fiber.current.instance_variable_set(:@yielder, y) send(meth, *args) end description = "#{inspect}:#{meth}" cons.define_singleton_method :inspect do state = if @fiber.alive? then "running" else @result.inspect end "#<Consumer: #{description} (#{state})>" end cons end
Creates a new Transformer
instance that wraps the given method. This is analogous to using Kernel#enum_for to create an Enumerator
instance, or using Object#consum_for
to create a Consumer
instance. The method is not executed immediately. The resulting Transformer
can be connected to an enumerable (using transformer.in_connect(enum)) or to a sink (using transformer.out_connect(sink)). The point at which the transformer method gets started depends on how it is connected; in any case however, the method will be called with the args
given to trans_for. See Transformer
for details.
Within the transformer method, await
can be used to read the next input value (as in a Consumer
, compare Object#consum_for
), and yield can be used to produce an output value (i.e., when it is called, the method is given a block which accepts its output).
Example:
def running_sum(start) result = start loop { result += await; yield result } end tr = trans_for :running_sum, 3 #=> #<Transformer: main:running_sum> sums = (1..10).out_connect(tr) #=> #<Enumerator: #<Transformer: main:running_sum> <= 1..10> sums.to_a #=> [4, 6, 9, 13, 18, 24, 31, 39, 48, 58]
# File lib/coroutines.rb, line 200 def trans_for(meth, *args) trans = Transformer.new do |y| Fiber.current.instance_variable_set(:@yielder, y) send(meth, *args, &y.method(:yield)) end description ="#{inspect}:#{meth}" trans.define_singleton_method :inspect do "#<Transformer: #{description}>" end trans end