On Thu August 7 2003 3:03 am, Jim Weirich wrote:
> Actually, no.  One of the useful things to do with continuations is to
> stash them away for later execution.  If cc is the continuation of
> "Continuation.new", then the continuation has already been executed by
> the time you get access to it.  The block approach does not have this
> problem.  

Continuation.new was meant as a replacement of callcc.  The continuation would 
still be executed by Continuation#call, which in my mind, would bring you 
back to the point immediately after Continuation.new had returned.
 
> How would you do the same thing with Continuation.new ?

Well, in this case, maybe with Continuation.new acting exactly like callcc 
does now.  I just think it would look a little cleaner than it does now.  
"callcc" seems deceptive because you're not actually calling the 
continuation, you're evaluating a block and passing it the continuation, 
which it may call later.  I think this syntax:

Continuation.new { |normal_cc|
  Continuation.new { |abort_cc| f(normal_cc, abort_cc) }
  nil
}

Makes it more clear that the continuation is being created there, but called 
later.

The reason I like the idea of a no-block form of Continuation.new is that it 
would make this:

arr = [ "Freddie", "Herbie", "Ron", "Max", "Ringo" ]
callcc{|$cc|}
puts(message = arr.shift)
$cc.call unless message =~ /Max/

Freddie
Herbie
Ron
Max

Much more clear:

arr = [ "Freddie", "Herbie", "Ron", "Max", "Ringo" ]
cc = Continuation.new
puts(message = arr.shift)
cc.call unless message =~ /Max/

Freddie
Herbie
Ron
Max

In my mental image of how Continuation.new would work, if a block is given, 
Continuation#call resumes at the end of the block, just like it does now, but 
if no block is given, it would resume right at the point where the 
constructor returns, and the value is assigned to cc.

The only thing this doesn't address is the idea of callcc returning the value 
given by Continuation#call.  This might mean that Continuation.new isn't the 
right syntax for the block version.  Something like Continuation.run or 
Continuation.run_block might be more appropriate for that version.

Here's one that seems to work for me:

class Continuation
  def self.new
    cc = nil
    callcc {|cc| return cc}
    cc
  end

  def self.run
    callcc {|cc| yield(c) }
  end
end

irb(main):028:0> def countToFive
                   n=0
                   cc = Continuation.new
                   print "#{n} => "; n += 1; puts n
                   if 5 != n then cc.call end
                   n
                 end
=> nil
irb(main):029:0> countToFive
0 => 1
1 => 2
2 => 3
3 => 4
4 => 5
=> 5
irb(main):030:0> Continuation.run {|cont| cont.call(5, 5) }
=> [5, 5]