Return from ensure

Hi, Rubyists

Actually, I saw a remark on ruby-talk once that “return” is dagerous,
however I could not imagine it is that dangerous. Today I spent 2 hours
debugging the code that looked perfectly normal otherwise. I was able reduce
the code to the following fragment:

def test
begin
raise "ERROR"
ensure
return "some value"
end
end

test
puts “Nothing happened”

Yes, it prints out “Nothing happened”, and if you comment out “return” you
will see the exception. I just wanted to provide a return value for the
function here, so I naturally used “return” statement. I know that in Ruby
you can return something without explicit “return” and I usually do this
every time. However, at that unfortunate moment my instinct injected
"return" – and, here we go, 2 hours of fun.

Any comments?

Gennady.

Gennady wrote:

Yes, it prints out “Nothing happened”, and if you comment out “return” you
will see the exception. I just wanted to provide a return value for the
function here, so I naturally used “return” statement. I know that in Ruby
you can return something without explicit “return” and I usually do this
every time. However, at that unfortunate moment my instinct injected
“return” – and, here we go, 2 hours of fun.

Any comments?

Don’t trust your instincts next time? :wink:

“Gennady” gfb@tonesoft.com schrieb im Newsbeitrag
news:001101c32624$5aef3490$c20ca8c0@gfb…

Hi, Rubyists

Actually, I saw a remark on ruby-talk once that “return” is dagerous,
however I could not imagine it is that dangerous. Today I spent 2 hours
debugging the code that looked perfectly normal otherwise. I was able
reduce
the code to the following fragment:

def test
begin
raise “ERROR”
ensure
return “some value”
end
end

test
puts “Nothing happened”

Yes, it prints out “Nothing happened”, and if you comment out “return”
you
will see the exception. I just wanted to provide a return value for the
function here, so I naturally used “return” statement. I know that in
Ruby
you can return something without explicit “return” and I usually do this
every time. However, at that unfortunate moment my instinct injected
“return” – and, here we go, 2 hours of fun.

Any comments?

“ensure” is inappropriate for catching exceptions and returning something
else. You must use “rescue” for this. The purpose of “ensure” is to have
a piece of code that is invoked regardless of how the block is exited.
This code however should only do cleanup and not modification of the exit
procedure - as you have experienced.

You’ll find this very nicely documented in the pickaxe chapter
“Exceptions, Catch, and Throw”.

Regards

robert

“Gennady” gfb@tonesoft.com schrieb im Newsbeitrag
news:001101c32624$5aef3490$c20ca8c0@gfb…

Hi, Rubyists

Actually, I saw a remark on ruby-talk once that “return” is dagerous,
however I could not imagine it is that dangerous. Today I spent 2 hours
debugging the code that looked perfectly normal otherwise. I was able
reduce
the code to the following fragment:

def test
begin
raise “ERROR”
ensure
return “some value”
end
end

test
puts “Nothing happened”

Yes, it prints out “Nothing happened”, and if you comment out “return”
you
will see the exception. I just wanted to provide a return value for the
function here, so I naturally used “return” statement. I know that in
Ruby
you can return something without explicit “return” and I usually do this
every time. However, at that unfortunate moment my instinct injected
“return” – and, here we go, 2 hours of fun.

Any comments?

“ensure” is inappropriate for catching exceptions and returning something
else. You must use “rescue” for this. The purpose of “ensure” is to have
a piece of code that is invoked regardless of how the block is exited.
This code however should only do cleanup and not modification of the exit
procedure - as you have experienced.

You’ll find this very nicely documented in the pickaxe chapter
“Exceptions, Catch, and Throw”.

I understand perfectly well that I should not have done this. And in fact I
refactored the code so there’s no return from ensure. However, my point was
that it should have been handled by Ruby better, either ignoring return in
the presence of an exception and going on with whatever current exception
handling were in place, or at least give some kind of a warning at compile
time. Or simply advertising it as a language feature, what seems to me now
as a good idea.

Actually my initial intent was preserving the data collected by the class
that raised the exception so far and retruning a value if everything was OK.
The exception was supposed to be handled by some other class that would
adjust input criteria accordingly and continue.

By the way, I re-read the pickaxe chapter you reffer to, very nice and
informative one indeed. However there’s nothing there on the issue I have
raised, no “gotcha’s” on the fact that return from ensure in practice means
ignoring all exceptions. Now that I know this :slight_smile: I am not sure if it is a
side effect or the guarateed language behaviour.

Thanks for replying, Robert. I did not get many responces on this,
surprisingly.

P.S. Hmm, I just tested that return from “finally” in Java also means
ignoring exceptions. Interesting, I would never have thought. So it can be
regarded as a guaranteed feature after all.

···

----- Original Message -----
From: “Robert Klemme” bob.news@gmx.net
Newsgroups: comp.lang.ruby
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Monday, June 02, 2003 1:23 AM
Subject: Re: Return from ensure

Regards

robert

“Gennady” gfb@tonesoft.com schrieb im Newsbeitrag
news:000901c3291d$154a09f0$c20ca8c0@gfb…

I understand perfectly well that I should not have done this.

Sorry, in that case I did not understand you correctly.

And in fact I
refactored the code so there’s no return from ensure. However, my point
was
that it should have been handled by Ruby better, either ignoring return
in
the presence of an exception and going on with whatever current
exception
handling were in place, or at least give some kind of a warning at
compile
time. Or simply advertising it as a language feature, what seems to me
now
as a good idea.

Yes. Although I feel a bit wary about this, because for catching and
returning we still have ensure. IMHO it should not be allowed to return
from an ensure or have the interpreter warn about this.

Actually my initial intent was preserving the data collected by the
class
that raised the exception so far and retruning a value if everything was
OK.
The exception was supposed to be handled by some other class that would
adjust input criteria accordingly and continue.

But you would to this in an rescue clause. If all is well, return the
value otherwise rethrow by simple writing “raise” on a line. (See the
example in the referenced chapter.)

By the way, I re-read the pickaxe chapter you reffer to, very nice and
informative one indeed. However there’s nothing there on the issue I
have
raised, no “gotcha’s” on the fact that return from ensure in practice
means
ignoring all exceptions.

Yes indeed, that’s true. Maybe others have thought it so evident that you
typically won’t return from an ensure section so they did not see it
necessary to write a sentence about this.

Now that I know this :slight_smile: I am not sure if it is a
side effect or the guarateed language behaviour.

Thanks for replying, Robert. I did not get many responces on this,
surprisingly.

Um, well, often error handling is neglected… :-}

P.S. Hmm, I just tested that return from “finally” in Java also means
ignoring exceptions. Interesting, I would never have thought. So it can
be
regarded as a guaranteed feature after all.

Yes, I checked with the JLS. It’s a bit scattered: in 14.1 they define an
abrupt completion as one of break, continue, return or throw. In 14.19.2
they say that if a finally clause completes abruptly for some reason S
then the whole try clause terminates for this reason S. In our case S ==
“return”.

14.1
http://java.sun.com/docs/books/jls/second_edition/html/statements.doc.html#5894

14.19.2
http://java.sun.com/docs/books/jls/second_edition/html/statements.doc.html#236653

Cheers

robert

Newsgroups: comp.lang.ruby

···

----- Original Message -----
From: “Robert Klemme” bob.news@gmx.net
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Monday, June 02, 2003 9:07 AM
Subject: Re: Return from ensure

But you would to this in an rescue clause. If all is well, return the
value otherwise rethrow by simple writing “raise” on a line. (See the
example in the referenced chapter.)

I just wanted to save on typing ;-). Now I save the data in “ensure” in an
array initialized before my begin/ensure/end block and return it after the
block. In case of an excetpion, the data is still preserved and no return
executed. It even conveys the intent much better.

Gennady.

“Gennady” gfb@tonesoft.com schrieb im Newsbeitrag
news:000f01c32924$b93733b0$c20ca8c0@gfb…

But you would to this in an rescue clause. If all is well, return the
value otherwise rethrow by simple writing “raise” on a line. (See the
example in the referenced chapter.)

I just wanted to save on typing ;-). Now I save the data in “ensure” in an
array initialized before my begin/ensure/end block and return it after the
block. In case of an excetpion, the data is still preserved and no return
executed. It even conveys the intent much better.

Much better. Although I have to admit what kind of operation this is that
is meant to return some data which it apparently does retrieve successfully
even in case of an exception.

Cheers

robert