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