The timeless repository

Exception#continue

Written by Magnus Holm

Imagine a world with Exception#continue:

10.times do |i| begin raise "OH NO!" puts "OH YES! #{i}" i += 1 rescue => err if i < 5 # Nah, let's ignore this exception and just continue # from where it was raised. err.continue else raise err end end end

Oh, that’s right. This is Ruby. Forty lines later:

class Exception class NoContinuation < StandardError end attr_accessor :continuation def continue raise NoContinuation unless continuation.respond_to?(:call) continuation.call end end module NeverGonnaLetYouDown def raise(exception = RuntimeError, string = nil, array = caller) # With a single String argument, raises a # RuntimeError with the string as a message. if exception.is_a?(String) string = exception exception = RuntimeError end callcc do |cc| obj = exception.exception(string) obj.set_backtrace(array) obj.continuation = cc super obj end end def fail(exception = RuntimeError, string = nil, array = caller) raise(exception, string, array) end end class Object include NeverGonnaLetYouDown end