I know this has been on the table before, but I really see no reason not
to allow do/end blocks to have rescue clauses on them, i.e.
foo do
bar
rescue
baz
end
and even
foo do
bar
rescue
baz
ensure
bur
end
These would be equivalent to
foo do
begin
bar
rescue
baz
ensure
bur
end
end
When an ensure clause is added, the expression evaluated therein will
always be the return value of a call to the block – just as if there
was a begin/end block inside the do/end block.
This wouldn’t offer any new functionality, but would make the use of
rescue and ensure clauses more consistent – currently they work with
begin, class, and def blocks (more?).
There’s of course the case of the curly bracket block syntax, but I see
no need to support it there – I think it’s most commonly used with
one-liners, where rescuing may be overkill.
I’d like some feedback, and if its generally positive, I’ll post an RCR.
Just playing Devil’s Advocate, what’d happen with this:
File.open(‘somefile’) do |f|
puts f.read
end rescue puts “Can’t open”
The same as there would now; since the rescue clause is not inside the
do/end block, it is not affected by this proposal.
The difference would be that your version would also rescue exceptions
raised by File.open, while the proposed syntax would only rescue
exceptions raised within the block given to File.open.
But I like the devil’s advocate approach, it makes the proposals sharper
On Fri, 2006-05-19 at 00:34 +0900, Daniel S. wrote:
raised by File.open, while the proposed syntax would only rescue
exceptions raised within the block given to File.open.
Does that mean that with the proposed syntax, to rescue an exception
from this File.open, we’d have to use:
begin
File.open('somefile') do |f|
puts f.read
rescue
# exception from f.read
end
rescue
# exception from File.open
end
But I like the devil’s advocate approach, it makes the proposals sharper
In truth, I think I’m in favour of this change, especially if it
could be done so that the rescue catches exceptions from the block as
well as those from the method to which the block is attached (if any).
As I imagine it right now, rescue clauses on do/end blocks would only
rescue exceptions raised inside that block – to rescue exceptions
raised with the method the block is attached to, one must wrap the
method with begin/end.
But I like the devil’s advocate approach, it makes the proposals sharper
In truth, I think I’m in favour of this change, especially if it
could be done so that the rescue catches exceptions from the block as
well as those from the method to which the block is attached (if any).
I’m not sure I’d like that – I see a block attached to a method call as
being, in some sense, a child of that call, another kind of argument if
you will; having the child rescue exceptions raised by the parent seems
unintuitive to me, though others may feel different.
Setting up and tearing down an exception handler for every block
invocation is going to be expensive.
Couldn’t the setup/teardown be done only if a rescue/ensure clause was
actually present? It also seems to me that this would mean the the
setup/teardown would have to be in the block itself, not in the calling
method. Thus making it hard to rescue exceptions from the calling
method (as some have suggested).
For the record,
(A) if it can be done efficiently, I’m for it.
(B) I’m not in favor of rescuing exceptions from the parent method.
That just seems backwards to me.
The main reason that Matz has opposed it before is:
foo {
bar
rescue
baz
}
It does look odd, but I think people will just get used to it.
I think it looks too odd. The do/end and the curly bracket syntaxes are
used in different places – if I needed error handling, I would never
use the curly brackets anyway. I see the problem, though; I just don’t
think it’s big enough to block the implementation of this.
In truth, I think I’m in favour of this change, especially if it
could be done so that the rescue catches exceptions from the block as
well as those from the method to which the block is attached (if any).
I’m not sure I’d like that – I see a block attached to a method call as
being, in some sense, a child of that call, another kind of argument if
you will; having the child rescue exceptions raised by the parent seems
unintuitive to me, though others may feel different.
I agree with Daniel. It should only rescue exceptions raised in the
block, not the parent/holder/caller/receiver of the block.
I think it looks too odd. The do/end and the curly bracket syntaxes are used
in different places – if I needed error handling, I would never use the
curly brackets anyway.
I’m not sure I get that distinction – I mean, I understand that you
do it that way, but I’m not sure there’s any generally closer
association between do/end and rescuing than there is between {} and
rescuing. Also, they’re sometimes used in the same places, but by
different people
Setting up and tearing down an exception handler for every block
invocation is going to be expensive.
Couldn’t the setup/teardown be done only if a rescue/ensure clause was
actually present? It also seems to me that this would mean the the
setup/teardown would have to be in the block itself, not in the
calling
method.
I forgot that the parser will just take care of it. The patch was
easy, applies to a recentish copy of the 1.8 branch: