From: "James M. Lawrence" Date: 2009-03-23T11:29:12+09:00 Subject: Cond: Resolve errors without unwinding the stack Hello -- Here is a portion of the readme for this new project. For those unfamiliar with condition systems, I recommend watching a few minutes of Seibel in the video mentioned below. = Cond == Description Resolve errors without unwinding the stack. == Synopsis require 'cond' include Cond def divide(x, y) restartable do restart :return_this_instead do |value| return value end raise ZeroDivisionError if y == 0 x/y end end handling do handle ZeroDivisionError do invoke_restart :return_this_instead, 42 end puts divide(10, 2) # => 5 puts divide(18, 3) # => 6 puts divide(4, 0) # => 42 puts divide(7, 0) # => 42 end == Install % gem install cond or % ruby install.rb [--uninstall] == Overview Cond allows errors to be handled near the place where they occur, before the stack unwinds. It offers several advantages over exceptions while peacefully coexisting with the standard exception behavior. The system is divided into two parts: _restarts_ and _handlers_. When +raise+ is called and there is a matching handler for the error, the normal mechanism of unwinding the stack is suspended while the handler is called instead. At this time, the handler may invoke one of the available restarts. A handler may find a way to negate the problem and, by invoking a restart, allow execution to continue from a place proximal to where +raise+ was called. Or a handler may choose to allow the exception to propagate in the usual unwinding fashion, as if the handler was never called. Cond is 100% compatible with the built-in exception-handling system. We may imagine that Ruby had this handler/restart functionality from the very beginning, but everyone had forgotten to write restarts. And since no restarts were available, no handlers were written. == Background Cond is stolen from the Common Lisp condition system. Peter Seibel discusses the advantages of handlers and restarts in the following video. I have fast-forwarded to the most relevant part, though the whole talk is worthwhile. http://video.google.com/videoplay?docid=448441135356213813#46m07s The example he shows is taken from his book on Lisp, http://www.gigamonkeys.com/book/beyond-exception-handling-conditions-and-restarts.html See readmes/seibel_pcl.rb for a Ruby translation. == Synopsis 2.0 x, y = 7, 0 handling do handle ZeroDivisionError do |exception| invoke_restart :return_this_instead, 42 end result = restartable do restart :return_this_instead do |value| leave value end raise ZeroDivisionError if y == 0 x/y end puts result # => 42 end == Technical Notes Cond has been tested on MRI 1.8.6, 1.8.7, 1.9, and the latest jruby. Each thread keeps its own list of handlers, restarts, and other data. All operations are fully thread-safe. It is not required to include Cond. The includable methods of +Cond+ are module_functions and are thus callable via e.g. Cond.handling. +Cond+ nests private modules and classes inside Cond::CondPrivate in order to improve the hygiene of include Cond and encourage its use. Except for the redefinition +raise+, Cond does not silently modify any of the standard classes == Links * Documentation: http://cond.rubyforge.org * Rubyforge home: http://rubyforge.org/projects/cond/ * Download: http://rubyforge.org/frs/?group_id=7916 * Repository: http://github.com/quix/cond/tree/master == I am open to suggestions on anything from syntax to terminology. For example I experimented with a "body" block so that the the main code could appear before the handlers and restarts. And I once used "on" to replace both "handle" and "restart", e.g., "on ZeroDivisionError do ...". James M. Lawrence -- Posted via http://www.ruby-forum.com/.