Throwing exceptions into continuations

Hi all. I’m playing around with Ruby because I like experimenting with
concurrency systems, and found out it has continuations.

I’m going to be calling user-defined code inside of a callcc block,
and the user-defined code will either return a value or raise an
error, and I want that value or error to be passed on to the
continuation.

I can’t find any way to throw into the continuation. If there is no
way, can I request that a #throw method be added, or something like
that?

The only alternative I could think of is to have special code on the
calling side of the callcc that will watch the return value to see if
it is a array of two elements, the first being
:special-internal-throw-exception-bit, and if so, throwing the second
element of the array. This isn’t what I want, though, especially
because it won’t maintain the stack trace from the other side.

···


Twisted | Christopher Armstrong: International Man of Twistery
Radix | Release Manager, Twisted Project
---------+ http://twistedmatrix.com/users/radix.twistd/

Hi all. I’m playing around with Ruby because I like experimenting with
concurrency systems, and found out it has continuations.

I’m going to be calling user-defined code inside of a callcc block,
and the user-defined code will either return a value or raise an
error, and I want that value or error to be passed on to the
continuation.

Is there a reason why you are using continuations for this? Perhaps
some other construct like procs or threads would work better.

I can’t find any way to throw into the continuation. If there is no
way, can I request that a #throw method be added, or something like
that?

I’m not entirely sure what you mean by “throw into”. Do you want to
cause an exception to occur in the middle of the user-defined code?

There is a Thread#raise, if you want to use a thread. You can stop the
thread if you want it to stop running for a while.

The only alternative I could think of is to have special code on the
calling side of the callcc that will watch the return value to see if
it is a array of two elements, the first being
:special-internal-throw-exception-bit, and if so, throwing the second
element of the array. This isn’t what I want, though, especially
because it won’t maintain the stack trace from the other side.

You might be interested in what I did here:
RubyCollections download | SourceForge.net

There are two continuations: one doing the iterating and one waiting for
the next item from the iteration. The iteration loop is wrapped with a
begin/rescue block, and if I get the exception, it gets re-raised by the
caller with a backtrace that includes both the backtrace of the
iteration block and the backtrace of the code that called #next. Not
perfect, but it gives me all the information I need when I’m debugging.

Paul

···

On Sun, Jul 27, 2003 at 10:53:42AM +0900, Christopher Armstrong wrote:

Hi all. I’m playing around with Ruby because I like experimenting with
concurrency systems, and found out it has continuations.

I’m going to be calling user-defined code inside of a callcc block,
and the user-defined code will either return a value or raise an
error, and I want that value or error to be passed on to the
continuation.

I can’t find any way to throw into the continuation. If there is no
way, can I request that a #throw method be added, or something like
that?

You’re more likely to get a response if you can provide some kind of
starting point (even if its pseudo-code) for questions like this.

Here is an example of one inappropriate guess for your case.
It was difficult to make it this complex because (and I am being
serious), you start with some code and the complicated stuff
often reduces right down.
To others: I know, I can reduce this myself. Resist :slight_smile:

daz

class UserError < StandardError
def initialize(err)
@err = err
end
end

def user_stuff
rn = rand(15)
if rn > 10
puts “* Raising error #{rn} "
throw(:event, UserError.new(rn))
else
puts "
Returning value #{rn} *”
end
rn
end

10.times do
cc_ret = callcc do |cont|
rc = catch(:event) do
rc = user_stuff
puts ‘- no error -’
rc
end
rc
end
puts “cc: #{cc_ret.inspect}”; puts
end

output

  • Returning value 6 *
  • no error -
···

“Christopher Armstrong” radix@twistedmatrix.com wrote:
cc: 6

  • Returning value 8 *
  • no error -
    cc: 8
  • Raising error 12 *
    cc: #<UserError: UserError>

  • Returning value 0 *

  • no error -
    cc: 0
  • Returning value 2 *
  • no error -
    cc: 2
  • Returning value 5 *
  • no error -
    cc: 5
  • Returning value 10 *
  • no error -
    cc: 10
  • Raising error 12 *
    cc: #<UserError: UserError>

  • Raising error 13 *
    cc: #<UserError: UserError>

  • Returning value 6 *

  • no error -
    cc: 6

##############