In my last post I had a look at handling exceptions in Ruby and the functionality around that. In this post I’m going to look at how Ruby also allows us to unwind a single block of code without raising an exception. I’ve said before that exceptions should be exceptional – the functionality in Ruby offers a lightweight version of this within a single scope.
Let’s see some code
This is much easier to explain with an example.
The catch keyword defines a block with a given name. The block is processed normally until a throw statement is encountered.
When a throw statement is encountered Ruby will look up the call stack for a catch statement with the corresponding symbol. It will then unwind the call stack up to that point and terminate the block.
In this example the block will have two possible return values. If no number under 10 is generated the throw statement will never execute and the array of random numbers will be returned. If the throw statement does execute the block will simply return nil. Ruby also allows us to override this behavior – for example, instead of returning nil I might choose to return an empty array. We can do this by specifying a second parameter to the throw statement.
One of the reasons why it’s possibly not a good idea to overuse exceptions in your code is performance. Every time you raise an exception Ruby has to build a stack trace. If your exceptions are exceptional (as they should be) this won’t be a problem. However, if you’re using a large number of exceptions in a tight loop it could have a negative impact on performance. I’m assuming that a catch-throw block doesn’t need to create a stack trace – let’s see if we can get a rough idea of the performance impact.
As I mentioned, these are very rough performance estimates, but there does seem to be a significant performance difference between using exceptions and using a catch-throw block.
The catch-throw block seems to be a lightweight error handling mechanism – useful when you want to jump out of a nested construct during normal processing. The performance figures point to the same conclusion.