# module Continuation

### Public Class Methods

create(*args, &block) click to toggle source

# Continuation Extension¶ ↑

Creates a continuation in a way that is easier to use than callcc. On the initial call this will return the created Continuation and the arguments you gave to ::create in an Array. If you then issue .call() on the Continuation execution will jump back to the point of time where you initially invoked ::create, but this time it will return the Continuation and the arguments you supplied in an Array.

You can supply a block instead of default arguments which will cause that block to be executed once and its result to be returned along side the created Continuation, but this form is confusing and does only rarely make sense.

     # Count from 0 to 10
     cc, counter = Continuation.create(0)
     counter   #~> 0..10
     cc.call(counter + 1) if counter < 10

     # Implement something similar to Array#inject using Continuations.
     # For simplicity's sake, this is not fully compatible with the real
     # inject. Make sure that you understand Array#inject before you try
     # to understand this.
     class ::Array
       def cc_inject(value = nil)
         copy = self.clone
         cc, result, item = Continuation.create(value, nil)
         next_item = copy.shift
         if result and item
           # Aggregate the result using the block.
           cc.call(yield(result, item), next_item)
         elsif next_item
           # item not yet set and Array is not empty:
           # This means we did not get a value and thus need to use the
           # first item from the Array before we can start using the
           # block to aggregate the result.
           cc.call(next_item, result)
         end

         return result
      end
    end
    [1,2,3,4,5].cc_inject { |acc, n| acc + n } # => 15

    # File lib/facets/continuation.rb, line 48
    def Continuation.create(*args, &block)
      args = [args] if not args.nil? and not args.is_a? Array # 1.6.8 compatibility
      cc = nil; result = callcc {|c| cc = c; block.call(cc) if block and args.empty?}
      result ||= args
      return *[cc, *result]
    end