class Object

Constants

Multicast

convenience alias for Sink::Multicast (this is not defined when requiring just coroutines/base)

Public Instance Methods

await → obj click to toggle source

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
consum_for(method, *args) → consumer click to toggle source

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
trans_for(method, *args) → transformer click to toggle source

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