Rescue on do end blocks

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

Farrel Lifson wrote:

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

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.

···

On Mar 7, 2006, at 4:31 AM, Farrel Lifson wrote:

--
Eric Hodel - drbrain@segment7.net - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com

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

Farrel

···

On 3/7/06, Marcin Mielżyński <lopexx@autograf.pl> wrote:

Farrel Lifson wrote:
> 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

Farrel Lifson wrote:

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

Okay that kinda makes sense... kinda.

···

On 3/7/06, Marcin Mielżyński <lopexx@autograf.pl> wrote:

Farrel Lifson wrote:
> 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

Marcin Mielżyński wrote:

Farrel Lifson wrote:

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

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

Farrel Lifson wrote:

Okay that kinda makes sense... kinda.

:slight_smile:

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

Ah if that's the case then I can understand a bit more clearly why.
Still it would be a nice thing to have.

Thanks
Farrel

···

On 3/7/06, Marcin Mielżyński <lopexx@autograf.pl> wrote:

Farrel Lifson wrote:
> Okay that kinda makes sense... kinda.
>

:slight_smile:

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