Rescue / ensure in do..end blocks?

Greetings, ruby-talk!

As the subject suggests, I was wondering recently if there is a good reason why Ruby should not support rescue and ensure statements in do..end blocks.

They work in begin/end blocks:

   begin
     (a / b).to_s
   rescue ZeroDivisionError
     "division by zero"
   end

...and in methods:

   def div(a, b)
     (a / b).to_s
   rescue ZeroDivisionError
     "division by zero"
   end

...but inside a block, they do not work:

   def divall(num, denoms)
     denoms.map do |denom|
       (a / b).to_s
     rescue ZeroDivisionError
       "division by zero"
     end
   end

   (-> syntax error, unexpected keyword_rescue, expecting keyword_end)

I know of two ways to write such methods:

a) wrap the block body with begin/rescue:

   denoms.map do |denom|
     begin
       (a / b).to_s
     rescue ZeroDivisionError
       "division by zero"
     end
   end

b) use inline rescue (and thereby possibly hide bugs):

   denoms.map do |denom|
     (a / b).to_s rescue "division by zero"
   end

Is there any technical (or philosophical) reason this is not possible?
Would anyone else find it useful?

recmm

Hi,

...but inside a block, they do not work:

This is an interesting suggestion. I don’t know the reasons behind the
design of the language, but compared to the shortcut with "def" it
indeed sounds inconsistent.

It might be that the "def" keyword is somehow more "static" than the
"do/end" combination, making it easier to detect. Also, how do you want
to treat curly braces {...}? Currently, do...end and {...} are
equivalent except for the precedence. With your addition, do...end
would allow a "rescue" shortcut that {...} does not allow, thereby
breaking the symmetry between the two syntaxes.

b) use inline rescue (and thereby possibly hide bugs):

I have some time ago suggested to expand the one-line rescue statement
exactly because it swallows too many exceptions. The topic is still in
discussion on the Ruby bugtracker[1]. In summary, the idea appears to be
found to be good, but there has not yet been found an adequate syntax.
My most recent suggestion was to hijack the "in" keyword such that the
extended one-line rescue statement would look like this:

  (a / b).to_s rescue ZeroDivisionError in "division by zero"

Feel free to support this suggestion here or in the bugtracker or make a
better one. But I do think the one-line rescue statement needs an
overhaul.

Greetings
Marvin

[1]: Feature #6739: One-line rescue statement should support specifying an exception class - Ruby master - Ruby Issue Tracking System

···

Am Thu, 5 May 2016 13:23:53 +0200 schrieb Recursive Madman <recursive.madman@gmx.de>:

--
Blog: http://www.guelkerdev.de
PGP/GPG ID: F1D8799FBCC8BC4F

[...]
Currently, do...end and {...} are
equivalent except for the precedence. With your addition, do...end
would allow a "rescue" shortcut that {...} does not allow, thereby
breaking the symmetry between the two syntaxes.

Indeed. I meant to imply that the same would work {...} blocks, but also agree that it looks a bit weird:

   denoms.map { |denom|
     (a / b).to_s
   rescue ZeroDivisionError
     "division by zero"
   }

or even in a one-line version:

   denoms.map { |b| a/b ; rescue ZeroDivisionError ; "devision by zero" }

in which case it becomes hard to distinguish from an inline rescue.

I have some time ago suggested to expand the one-line rescue statement
exactly because it swallows too many exceptions. The topic is still in
discussion on the Ruby bugtracker[1].

I followed that discussion a while ago, but haven't looked recently.

In summary, the idea appears to be
found to be good, but there has not yet been found an adequate syntax.
My most recent suggestion was to hijack the "in" keyword such that the
extended one-line rescue statement would look like this:

   (a / b).to_s rescue ZeroDivisionError in "division by zero"

True, that would work for the one-line example.

Feel free to support this suggestion here or in the bugtracker or make a
better one. But I do think the one-line rescue statement needs an
overhaul.

I'm all in favor of removing the differences in functionality between inline- and block-rescue!

Though in this thread I came to argue that the difference in syntax between methods and blocks is also unnecessary :slight_smile:

cheers,

recmm

···

On 05/05/2016 02:22 PM, Marvin Gülker wrote:

[1]: Feature #6739: One-line rescue statement should support specifying an exception class - Ruby master - Ruby Issue Tracking System