Here's an example I came up with today while investigating continuations. Hope
this is useful to somebody trying to understand and use them. Feedback
welcome!

Output:

lizzy:~% ./continuation-example.rb 
1
2
exception seen, performing error handling (elem=3)
continuing
4
5
exception seen, performing error handling (elem=6)
continuing
7
8
exception seen, performing error handling (elem=9)
continuing
lizzy:~% 

Code:

#!/usr/bin/env ruby

# Have you ever had the problem of wanting to report some error condition from
# deep down within a set of nested method calls, but also wanting processing
# to continue right after the spot where the error occurred, after the error
# is reported and handled in the caller?
#
# While there are other ways to do this (e.g. using callbacks), this example
# shows how to do this using exceptions and continuations. The trick is to
# have the exception propagate the continuation to the appropriate caller
# which can then handle the error (print an error message, say) and cause
# processing to continue inside the method that saw the error by calling the
# continuation passed up.
#
# This code uses a Reader class instance to process a list of elements
# (numbers) using a screening function. The processing is facilitated using
# the Reader.each method. Inside this method, if the element passes screening
# it is yielded to the caller, else an exception is raised. The caller
# processes the exception, then causes processing to continue inside the
# Reader.each method, while passing a hint into it telling it how to continue.
# In this particular example, the screening test consists of checking whether
# a list element is divisible by 3, if which case it is considered "bad".
# Also, when a maximum of 3 errors is seen (as indicated by the caller)
# processing of list elements stops.

MAX_ERRORS = 3

class CCException < Exception
  attr_reader :cc, :elem
  def initialize(cc, elem)
    @cc, @elem = cc, elem
  end
end

class Reader
  def initialize(arr)
    @arr = arr
  end
  def each(check)
    cc = nil
    @arr.each do |elem|
      if check.call(elem)
	ok_to_continue = Kernel.callcc do |cc|
	  raise CCException.new(cc, elem)
	end
	break unless ok_to_continue
      else
	yield elem
      end
    end
  end
end

list = [1,2,3,4,5,6,7,8,9,10,11,12]
rdr = Reader.new(list)
errors = 0
# Returns whether we consider an element 'bad'
check = proc {|elem| elem % 3 == 0}
begin
  rdr.each(check) do |elem|
    puts elem
  end
rescue CCException => exc
  errors += 1
  puts "exception seen, performing error handling (elem=#{exc.elem})"
  # ...error handling...
  puts "continuing"
  exc.cc.call(errors < MAX_ERRORS)
end

exit

-- 
Jos Backus
jos at catnook.com