The maze book for programmers!
mazesforprogrammers.com

Algorithms, circle mazes, hex grids, masking, weaving, braiding, 3D and 4D grids, spheres, and more!

DRM-Free Ebook

The Buckblog

assorted ramblings by Jamis Buck

begin + else

8 February 2007 — 1-minute read

Even after 6+ years, Ruby still continues to surprise and delight me. My latest discovery (thanks to Mauricio’s Happy 2007 challenge) is that begin/end blocks accept (in addition to rescue and ensure) an else clause:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
begin
  # main code here
rescue SomeException
  # ...
rescue AnotherException
  # ..
else
  # stuff you want to happen AFTER the main code,
  # but BEFORE the ensure block, but only if there
  # were no exceptions raised. Note, too, that
  # exceptions raised here won't be rescued by the
  # rescue clauses above.
ensure
  # stuff that should happen dead last, and
  # regardless of whether any exceptions were
  # raised or not.
end

If you don’t have an ensure clause, else is pretty much the same as just putting code immediately after the end, but if the order matters (something should happen before ensure, and only if the main code succeeded, and should not be subject to being rescued if something goes wrong), then else is your man.

Reader Comments

I remember reading about this in the Pickaxe book back when I was first learning Ruby. I have never quite understood the need for this. Compare the following:

<macro:code> begin possibly_failable_action run_this_only_when_success rescue SomeException run_this_only_on_failure ensure run_this_no_matter_what end <macro:code>

vs.

<macro:code> begin possibly_failable_action rescue SomeException run_this_only_on_failure else run_this_only_when_success ensure run_this_no_matter_what end <macro:code>

These both should do the same thing but the first one gets by without the extra “else” construct. So that although it is neat and arguably more clear in it’s meaning I have always found myself doing the first method. Probably because other languages don’t have the nifty “else” construct so my mind seems to always be pushing me towards the first method.

Arg.. I guess I’m just going to give up on trying to use that nifty ruby formatting. :)

The closing tags needs to be </macro:code>, and then it should work fine. (That’s probably my fault; there was a typo in my previous explanation of how this worked.)

Eric, the difference between the former and the latter examples you gave is this: in the first, any exception in “run_this_only_when_success” will cause the rescue clause to be invoked, whereas when using the ‘else’, exceptions in the else clause are not rescued.

It’s a subtle difference, but I found a need for it today and saw the light. :)

I had the exact same reaction as Eric. Of course, that is probably do to the way this is achieved in other languages that don’t have this construct.

I suppose the benefit of this is readability—the code that is evaluated only in event of success is explicitly denoted as a conditional block.

Eric, I may be misunderstanding the use of the else, but I think the key is that the code in the else part is not checked for exceptions. Any exception that happens will bubble up the call stack as normal. I can’t see a super good reason for this at the moment, but it is slightly different from your first code snippet.

Jamis, What was your use case?

I agree about the usefulness of the “else” clause in begin/end blocks. It can turn a piece of code like this:
1
2
3
4
5
6
7
8
9
def cancel
  begin
    # Some code that might raise an exception
  rescue
    return false
  end

  return true
end
1
2
3
4
5
6
7
def cancel
  # Some code that might raise an exception
rescue
  return false
else
  return true
end

It’s a matter of taste, definitely, but I prefer the latter for cleanliness (that is, why explicitly use the “begin” statement when it is done for you?).

Beautiful, Adam, thanks for that example.

I don’t think “else is pretty much the same as just putting code immediately after the end”, without the ensure clause.

Let’s say you catch an exception but ignore it. Then your else part won’t run. Whereas if the else part is after end, then it will still run.


begin
 '3'+3
rescue TypeError
 puts 'err'
else
 puts 'no err'
end

isn’t the same as


begin
 '3'+3
rescue TypeError
 puts 'err'
end
puts 'no err'

I almost want to think of it as ‘sucess’ instead of ‘else’, because it’s run when there’s a lack of an exception.

But how is Adam’s example different from this?</>


def cancel
  # Some code that might raise an exception
  return true # will get here if no exceptions raised
rescue
  return false
end

Eric, it’s not. The two are (semantically) identical, though Adam’s makes it clearer what happens when no exceptions are raised. Some might prefer it one way, some another. Ruby does, after all, follow the TIMTOWTDI philosophy.

I’m not sure that Ruby’s philosophy or set of goals explicitly includes TIMTOWTDI. Matz has said that Ruby follows good user interface design. And many have said that Ruby follows the Principle of Least Surprise. You can read a bit more on the Wikipedia section on Ruby’s philosophy.

As for what’s clearer, that tends to be personal. But when I read the block above the rescue blocks, I interpret that as what happens unless an exception occurs. I don’t think breaking that up and spreading that out helps all that much.