Forum: Ruby Cond: Resolve errors without unwinding the stack

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
James M. (Guest)
on 2009-03-23 04:32
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=4484411353...

The example he shows is taken from his book on Lisp,

http://www.gigamonkeys.com/book/beyond-exception-h...

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 <tt>include Cond</tt>.  The includable methods
of +Cond+ are <tt>module_function</tt>s and are thus callable via e.g.
<tt>Cond.handling</tt>.

+Cond+ nests private modules and classes inside Cond::CondPrivate in
order to improve the hygiene of <tt>include Cond</tt> 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
This topic is locked and can not be replied to.