[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

else inside rescue is useless?

cap

12/11/2006 12:17:00 PM

http://www.awprofessional.com/bookstore/product.asp?isbn=067232884...

The "The ruby way" book said

[quote]
In the event that error types are specified, it may be that an
exception does not match any of these types. For that situation, we are
allowed to use an else clause after all the rescue clauses.

begin
# Error-prone code...
rescue Type1
# ...
rescue Type2
# ...
else
# Other exceptions...
end

[/quote]

but actually, I found the "else" clause is only executed when there is
no exception been thrown,such as :

-------------------------
begin
puts "do something"
rescue NameError
puts "name error #{$!}"
else
puts "else #{$!}"
end
--------------------------

the result is

-------------------
do something
else
------------------

so the "else" clause is useless because we can simply put the content
of "else" caluse to the last line in the "begin" block before the first
"rescue"

Am I wrong or the book is wrong?

my ruby version is
ruby 1.8.4 (2005-12-24) [i686-linux]

14 Answers

Robert Klemme

12/11/2006 1:51:00 PM

0

On 11.12.2006 13:17, cap wrote:
> http://www.awprofessional.com/bookstore/product.asp?isbn=067232884...
>
> The "The ruby way" book said
>
> [quote]
> In the event that error types are specified, it may be that an
> exception does not match any of these types. For that situation, we are
> allowed to use an else clause after all the rescue clauses.
>
> begin
> # Error-prone code...
> rescue Type1
> # ...
> rescue Type2
> # ...
> else
> # Other exceptions...
> end
>
> [/quote]

This is plain wrong - at least in 1.8.5. The Pickaxe says the "else"
clause is executed if there was *no exception*. To catch any exception
you would have to replace the "else" with "rescue Exception => e" as
David indicated. However, there's a glitch (read on).

> but actually, I found the "else" clause is only executed when there is
> no exception been thrown,such as :
>
> -------------------------
> begin
> puts "do something"
> rescue NameError
> puts "name error #{$!}"
> else
> puts "else #{$!}"
> end
> --------------------------
>
> the result is
>
> -------------------
> do something
> else
> ------------------
>
> so the "else" clause is useless because we can simply put the content
> of "else" caluse to the last line in the "begin" block before the first
> "rescue"
>
> Am I wrong or the book is wrong?

I think the book is wrong - and there is also a difference between the
Pickaxe and the interpreter implementation (unfortunately). Try this code:

def foo(x)
begin
puts "x=#{x}"

case x
when 0
puts "returning"
return
when 1
raise "Some error"
when 2
raise NameError, "wrong name"
when 3
break "broken"
else
puts "do something"
end

puts "unsafe else"
rescue NameError
puts "name error: #{$!}"
else
puts "else"
ensure
puts "leaving!"
end
end

5.times do |i|
begin
foo i
rescue Exception => e
puts "Exception: #{e}"
end
end

With my 1.8.5 I see:

x=0
returning
leaving!
x=1
leaving!
Exception: Some error
x=2
name error: wrong name
leaving!
x=3
leaving!
Exception: unexpected break
x=4
do something
unsafe else
else
leaving!

What bugs me is that the "else" clause is not executed if it is left via
a "return". Taking the Pickaxe 2nd edition pg. 362 literally ("If an
else clause is present, its body is executed if no exceptions were
raised in code.") it would have to be executed in that case, too. So,
if the interpreter would behave as stated in the book, there was
actually a difference between the code at the end of the block and the
code inside the else clause.

Even in the current situation (where there seems to be no semantically
difference) putting code into the else clause instead of the end of the
block might have an advantage documentation wise.

Matz, can you clarify whether this is a bug in the interpreter or
whether the Pickaxe is wrong (or incomplete) here?

Kind regards

robert

Wilson Bilkovich

12/11/2006 4:05:00 PM

0

On 12/11/06, cap <capitain@gmail.com> wrote:
> http://www.awprofessional.com/bookstore/product.asp?isbn=067232884...
>
> The "The ruby way" book said
>
> [quote]
> In the event that error types are specified, it may be that an
> exception does not match any of these types. For that situation, we are
> allowed to use an else clause after all the rescue clauses.
>
> begin
> # Error-prone code...
> rescue Type1
> # ...
> rescue Type2
> # ...
> else
> # Other exceptions...
> end
>
> [/quote]
>
> but actually, I found the "else" clause is only executed when there is
> no exception been thrown,such as :
>
> -------------------------
> begin
> puts "do something"
> rescue NameError
> puts "name error #{$!}"
> else
> puts "else #{$!}"
> end
> --------------------------
>
> the result is
>
> -------------------
> do something
> else
> ------------------
>
> so the "else" clause is useless because we can simply put the content
> of "else" caluse to the last line in the "begin" block before the first
> "rescue"
>
> Am I wrong or the book is wrong?
>
> my ruby version is
> ruby 1.8.4 (2005-12-24) [i686-linux]
>
>
>

From the Rubinius test suite:
@count = 1
begin
p @count
raise ArgumentError, 'just kidding' unless @count > 3
rescue Exception => e
@count += 1
retry
else
p 7
ensure
p 8
end

this prints:
1
2
3
4
7
8

'else' only runs if no exception was raised.

Morton Goldberg

12/11/2006 7:53:00 PM

0

On Dec 11, 2006, at 8:55 AM, Robert Klemme wrote:

> def foo(x)
> begin
> puts "x=#{x}"
>
> case x
> when 0
> puts "returning"
> return
> when 1
> raise "Some error"
> when 2
> raise NameError, "wrong name"
> when 3
> break "broken"
> else
> puts "do something"
> end
>
> puts "unsafe else"
> rescue NameError
> puts "name error: #{$!}"
> else
> puts "else"
> ensure
> puts "leaving!"
> end
> end
>
> 5.times do |i|
> begin
> foo i
> rescue Exception => e
> puts "Exception: #{e}"
> end
> end
>
> With my 1.8.5 I see:
>
> x=0
> returning
> leaving!
> x=1
> leaving!
> Exception: Some error
> x=2
> name error: wrong name
> leaving!
> x=3
> leaving!
> Exception: unexpected break
> x=4
> do something
> unsafe else
> else
> leaving!
>
> What bugs me is that the "else" clause is not executed if it is
> left via a "return". Taking the Pickaxe 2nd edition pg. 362
> literally ("If an else clause is present, its body is executed if
> no exceptions were raised in code.") it would have to be executed
> in that case, too. So, if the interpreter would behave as stated
> in the book, there was actually a difference between the code at
> the end of the block and the code inside the else clause.

I would be horrified if the <else> were executed after a <return> --
<else> is not <ensure>. The Pickaxe book should be probably say: "If
an else clause is present, its body is executed if no exceptions were
raised and no exit was made in _code_ ." In fact, I just submitted an
erratum to this effect on the Pragmatic Programmer site.

> Even in the current situation (where there seems to be no
> semantically difference) putting code into the else clause instead
> of the end of the block might have an advantage documentation wise.

Also from Pickaxe: "Exceptions raised during the execution of the
else clause are not captured by rescue clauses in the same block as
the else." That seems to be a semantic difference.

Regards, Morton

Dave Thomas

12/11/2006 11:16:00 PM

0


On Dec 11, 2006, at 7:55 AM, Robert Klemme wrote:

> What bugs me is that the "else" clause is not executed if it is
> left via a "return". Taking the Pickaxe 2nd edition pg. 362
> literally ("If an else clause is present, its body is executed if
> no exceptions were raised in code.") it would have to be executed
> in that case, too. So, if the interpreter would behave as stated
> in the book, there was actually a difference between the code at
> the end of the block and the code inside the else clause.

Why would you expect the else clause to be executed if a return is
executed? That seems counter-intuitive to me.


Cheers


Dave

George

12/12/2006 3:50:00 AM

0

On 12/12/06, Robert Klemme <shortcutter@googlemail.com> wrote:
> Even in the current situation (where there seems to be no semantically
> difference) putting code into the else clause instead of the end of the
> block might have an advantage documentation wise.

If I'm understanding you correctly, there is a difference between:

begin
f
g
rescue E
end

and

begin
f
rescue E
else
g
end

and that is that any E's raised in #g won't be rescued in the latter.

Robert Klemme

12/12/2006 10:10:00 AM

0

On 12.12.2006 00:15, Dave Thomas wrote:
>
> On Dec 11, 2006, at 7:55 AM, Robert Klemme wrote:
>
>> What bugs me is that the "else" clause is not executed if it is left
>> via a "return". Taking the Pickaxe 2nd edition pg. 362 literally ("If
>> an else clause is present, its body is executed if no exceptions were
>> raised in code.") it would have to be executed in that case, too. So,
>> if the interpreter would behave as stated in the book, there was
>> actually a difference between the code at the end of the block and the
>> code inside the else clause.
>
> Why would you expect the else clause to be executed if a return is
> executed? That seems counter-intuitive to me.

I have low expectations with regard to the "else" clause but the book
clearly states that it is executed if there was no exception - that
includes the case where the block is left via a "return". Behavior and
description simply are not in sync, that's my point.

I can't remember ever having used this type of "else" clause so far so I
am pretty nonreligious about it. Although I can imagine a situation
where I would want to make sure some cleanup code is executed only when
there was no error in the block - and this includes leaving via
"return". Of course you can argue that leaving via "return" is a non
standard way to leave the block... As I said, I am pretty relaxed here.
I just think this needs some clarification - either way or the other.

Kind regards

robert

Dave Thomas

12/12/2006 1:32:00 PM

0


On Dec 12, 2006, at 4:10 AM, Robert Klemme wrote:

> I have low expectations with regard to the "else" clause but the
> book clearly states that it is executed if there was no exception -
> that includes the case where the block is left via a "return".
> Behavior and description simply are not in sync, that's my point.


Interesting: I'd honestly never have thought of that interpretation.
I guess in my mind, the semantics of return take precedence over most
other semantics, and I explicitly note the times where that's not the
case. Thanks for pointing out an alternative.

Do you feel I should also document the other places when a return
could be issued? For example, in the description of a while loop, I
say "executes body zero or more times as long as boolean-expression
is true." Should I add "or a return is executed or an exception is
thrown" to this and similar descriptions?

I kind of feel that this would clutter the descriptions, and that
most readers would make the assumption that return and exceptions
would break the flow. Is that an incorrect assumption?


Regards


Dave


Robert Klemme

12/12/2006 2:18:00 PM

0

On 12.12.2006 14:31, Dave Thomas wrote:
>
> On Dec 12, 2006, at 4:10 AM, Robert Klemme wrote:
>
>> I have low expectations with regard to the "else" clause but the book
>> clearly states that it is executed if there was no exception - that
>> includes the case where the block is left via a "return". Behavior
>> and description simply are not in sync, that's my point.
>
> Interesting: I'd honestly never have thought of that interpretation. I
> guess in my mind, the semantics of return take precedence over most
> other semantics, and I explicitly note the times where that's not the
> case. Thanks for pointing out an alternative.

Dave, you're welcome! I was probably in formal mode when reading that,
although I believe the situation here is a tad different from the
"while" loop case:

> Do you feel I should also document the other places when a return could
> be issued? For example, in the description of a while loop, I say
> "executes body zero or more times as long as boolean-expression is
> true." Should I add "or a return is executed or an exception is thrown"
> to this and similar descriptions?

Maybe just "... or the body of the loop is left via other control flow
statements". You could even add a footnote which enumerates them. :-)

> I kind of feel that this would clutter the descriptions, and that most
> readers would make the assumption that return and exceptions would break
> the flow. Is that an incorrect assumption?

I agree about cluttering and I think a change is not needed in this
cases - in other words, I believe it's not an incorrect assumption. :-)

I think the case with "else" clause after "rescue" clauses is a bit
different because control flow is not explicit like with loops. It is
immediately clear that "break", "return", "raise" and "throw" will
instantly leave the loop (is it?). However, with "rescue - else" we are
talking about less explicit control flow and so maybe a more explicit
description is helpful here.

As I said, it's probably a corner case and I have no idea how often this
"else" is actually used in applications. I for my part cannot remember
ever having used it - apart from the research for this thread.

It's a totally different question whether the behavior of the
interpreter should change so code in "else" clause is executed even for
a "return". There might be arguments in favor and against it. Maybe
Matz can shed some light about the reasoning why it is the way it is.

Kind regards

robert

dblack

12/12/2006 2:22:00 PM

0

dblack

12/12/2006 2:26:00 PM

0