We're hiring!

We're actively seeking designers and developers for all three of our locations.

Conditions and Exceptions

I recently learned about condition systems from this Axis of Eval post, and I’m exceptionally jealous of Lisp for this feature. Simply put, a condition is just an exception that doesn’t force you to unwind the stack. This is a very straightforward concept but, as the post details, it could have profound effects on the flow of your code once you understand how to use it.

In a traditional exception-handling scenario, you attempt to perform some action and provide a block of code to run if the action fails – by the time you know something went wrong, the action has ceased and the stack has already been unwound all the way up to your try/catch. That’s actually fine for a lot of cases, because once you’ve determined that this case is exceptional, no more work can really be done.

However, what if there’s an exception to the exception? If we know what things can go wrong, it is sometimes possible to recover from an error case, and it would be nice if our code could reflect that.

That’s what a condition system does. It makes no assumptions about your desire to unwind the stack and allows you to respond to the exception while it is being thrown. So when a condition says “I’m afraid I can’t continue with the value you’ve given me.”, your handler can reply “Oh, apologies my good sir, please proceed with this value instead.” and the plan goes off without a hitch.

Ready for some code?

There’s a gem for Ruby that implements this functionality, so let’s take a look at the example from that:

def do_stuff()
  error_occured = do_something()
  if error_occured
    raise_with_restarts(MyException.new(...)) { |restart_id|
      case restart_id
      when :ID1 then do_something_more()
      when :ID2 then do_something_even_more()
      end
    }
  end
end
 
begin
  do_stuff()
rescue MyException
  $!.restart(:ID1) if (boolean expression involving $! data)
end

This example is a little abstract, but even so, you can see how the code raising the exception provides a set of options for external code to resolve the issue and continue execution. Given this, I’m sure you can imagine how those options could map elegantly to a user interface for responding to error cases.

So what do you think? Are conditions something you would use if they were available in your language of choice? Are they an abomination unto the lord of stack-unwinding? Let me know in the comments.

Michael Harrington (7 Posts)

This entry was posted in Development Techniques. Bookmark the permalink. Both comments and trackbacks are currently closed.

One Comment

  1. Posted June 23, 2011 at 9:58 am

    Michael, I checked out the gem’s code (on github), and I think I follow through what’s going on, but that continuation is throwing me a curve.

    Can you describe of a concrete example where this pattern would be helpful?

    Also, I assume the continuation is what is giving the affect of allows you to respond to the exception while it is being thrown. Can you explain how that affects the exception stack/stack unwinding? Ruby continuations are this voodoo space-time wormhole that I have shied away from in the past but I’d like to learn more.