Rescue on do end blocks

F

Farrel Lifson

I've been playing around with rescue expressions and besides being put
on functions they also seem to work when defining classes (useful for
metaprogramming perhaps?)

irb(main):001:0> class Test
irb(main):002:1> raise
irb(main):003:1> rescue
irb(main):004:1> puts "Error"
irb(main):005:1> ensure
irb(main):006:1* puts "Cleaned up"
irb(main):007:1> end
Error
Cleaned up

However, why can they not be applied to do end blocks?

irb(main):016:0> [1,2,3].each do |num|
irb(main):017:1* num.upcase
irb(main):018:1> rescue
irb(main):019:1> puts "Error"
irb(main):020:1> ensure
irb(main):021:1* puts "Clened up"
irb(main):022:1> end
SyntaxError: compile error
(irb):18: syntax error
(irb):20: syntax error
from (irb):22

Farrel
 
M

Marcin Mielżyński

Farrel said:
I've been playing around with rescue expressions and besides being put
on functions they also seem to work when defining classes (useful for
metaprogramming perhaps?)

irb(main):001:0> class Test
irb(main):002:1> raise
irb(main):003:1> rescue
irb(main):004:1> puts "Error"
irb(main):005:1> ensure
irb(main):006:1* puts "Cleaned up"
irb(main):007:1> end
Error
Cleaned up

However, why can they not be applied to do end blocks?

irb(main):016:0> [1,2,3].each do |num|
irb(main):017:1* num.upcase
irb(main):018:1> rescue
irb(main):019:1> puts "Error"
irb(main):020:1> ensure
irb(main):021:1* puts "Clened up"
irb(main):022:1> end
SyntaxError: compile error
(irb):18: syntax error
(irb):20: syntax error
from (irb):22

Farrel

rescue must be enclosed in begin/end

[1,2,3].each do |num|
begin #!
num.upcase
rescue
puts "Error"
ensure
puts "Clened up"
end
end

lopex
 
M

Marcin Miel¿yñski

Farrel said:
Is there some reason why it can't be made more elegant like it is
currently for methods? Currently you can do this for methods:

def test
raise
rescue
puts "Error"
end

Because do/end is another form of { } (the difference is associativity)
and those are used to compose blocks.

Imagine:

sth.each{
raise
rescue
puts "Error"
}

which doesnt make sense for me

lopex
 
F

Farrel Lifson

T2theSB0aGF0IGtpbmRhIG1ha2VzIHNlbnNlLi4uIGtpbmRhLgoKT24gMy83LzA2LCBNYXJjaW4g
TWllbL958XNraSA8bG9wZXh4QGF1dG9ncmFmLnBsPiB3cm90ZToKPiBGYXJyZWwgTGlmc29uIHdy
b3RlOgo+ID4gSXMgdGhlcmUgc29tZSByZWFzb24gd2h5IGl0IGNhbid0IGJlIG1hZGUgbW9yZSBl
bGVnYW50IGxpa2UgaXQgaXMKPiA+IGN1cnJlbnRseSBmb3IgbWV0aG9kcz8gQ3VycmVudGx5IHlv
dSBjYW4gZG8gdGhpcyBmb3IgbWV0aG9kczoKPiA+Cj4gPiBkZWYgdGVzdAo+ID4gICByYWlzZQo+
ID4gcmVzY3VlCj4gPiAgIHB1dHMgIkVycm9yIgo+ID4gZW5kCj4gPgo+Cj4gQmVjYXVzZSBkby9l
bmQgaXMgYW5vdGhlciBmb3JtIG9mIHsgfSAodGhlIGRpZmZlcmVuY2UgaXMgYXNzb2NpYXRpdml0
eSkKPiBhbmQgdGhvc2UgYXJlIHVzZWQgdG8gY29tcG9zZSBibG9ja3MuCj4KPiBJbWFnaW5lOgo+
Cj4gc3RoLmVhY2h7Cj4gICAgIHJhaXNlCj4gICByZXNjdWUKPiAgICAgcHV0cyAiRXJyb3IiCj4g
fQo+Cj4gd2hpY2ggZG9lc250IG1ha2Ugc2Vuc2UgZm9yIG1lCj4KPiBsb3BleAo+Cj4K
 
M

Marcin Miel¿yñski

Farrel said:
Okay that kinda makes sense... kinda.

:)

Maybe somebody else will explain this better later on, but I'm sure that
the 'end' of 'do' has nothing to do with the 'end' of class, def, begin,
if, while etc..

lopex
 
F

Farrel Lifson

QWggaWYgdGhhdCdzIHRoZSBjYXNlIHRoZW4gSSBjYW4gdW5kZXJzdGFuZCBhIGJpdCBtb3JlIGNs
ZWFybHkgd2h5LgpTdGlsbCBpdCB3b3VsZCBiZSBhIG5pY2UgdGhpbmcgdG8gaGF2ZS4KClRoYW5r
cwpGYXJyZWwKCk9uIDMvNy8wNiwgTWFyY2luIE1pZWy/efFza2kgPGxvcGV4eEBhdXRvZ3JhZi5w
bD4gd3JvdGU6Cj4gRmFycmVsIExpZnNvbiB3cm90ZToKPiA+IE9rYXkgdGhhdCBraW5kYSBtYWtl
cyBzZW5zZS4uLiBraW5kYS4KPiA+Cj4KPiA6KQo+Cj4gTWF5YmUgc29tZWJvZHkgZWxzZSB3aWxs
IGV4cGxhaW4gdGhpcyBiZXR0ZXIgbGF0ZXIgb24sIGJ1dCBJJ20gc3VyZSB0aGF0Cj4gdGhlICdl
bmQnIG9mICdkbycgaGFzIG5vdGhpbmcgdG8gZG8gd2l0aCB0aGUgJ2VuZCcgb2YgY2xhc3MsIGRl
ZiwgYmVnaW4sCj4gaWYsIHdoaWxlIGV0Yy4uCj4KPiBsb3BleAo+Cj4K
 
E

Eric Hodel

I've been playing around with rescue expressions and besides being put
on functions they also seem to work when defining classes (useful for
metaprogramming perhaps?)
[...]

However, why can they not be applied to do end blocks?

irb(main):016:0> [1,2,3].each do |num|
irb(main):017:1* num.upcase
irb(main):018:1> rescue
irb(main):019:1> puts "Error"
irb(main):020:1> ensure
irb(main):021:1* puts "Clened up"
irb(main):022:1> end
SyntaxError: compile error
(irb):18: syntax error
(irb):20: syntax error
from (irb):22

This will make blocks much more expensive to call because you'll have
to perform the exception handler setup and teardown for each
invocation of the block which will give a slight performance
degradation:

require 'benchmark'

N = 10_000_000

Benchmark.bmbm do |bm|
bm.report 'without begin' do N.times { 0 } end
bm.report 'with begin' do N.times { begin 0 end } end
bm.report 'with rescue' do N.times { begin 0; rescue; end } end
end

user system total real
without begin 4.520000 0.020000 4.540000 ( 4.939785)
with begin 5.000000 0.030000 5.030000 ( 6.050101)
with rescue 6.720000 0.030000 6.750000 ( 7.716410)

While having an implicit begin won't give the same level of slowdown
if implemented in the compiler, there's no pressing need to add the
complexity to Ruby because it isn't the common case.
 
S

Shea Martin

Marcin said:
Because do/end is another form of { } (the difference is associativity)
and those are used to compose blocks.

Imagine:

sth.each{
raise
rescue
puts "Error"
}

which doesnt make sense for me

lopex

what about this

sth.each{

#my code
raise
#don't reach here

}rescue{

puts "Error"

}

kind like c++/java? I don't think it looks that great either, but then
I don't like the {} block in my (ruby) code anyway.

just my $0.02

~S
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,218
Latest member
JolieDenha

Latest Threads

Top