6

I tried this earlier and everyone got off on rescue block syntax. Please don't go there. Given the following working code:

begin (1..1000).each do |i| puts i sleep 1 end rescue Exception => e puts "\nCaught exception..." puts "Exception class: #{e.class}" end 

Pressing CTRL+C while it is running prints out "Caught exception...", as expected. What exactly is going on syntax wise in the rescue line, particularly between Exception and the variable e with the => in between?

The word "rescue" is a keyword... part of the ruby language. "e" is a variable, and could just as functionally be "a", "b", or "c". The following code works just as well.

begin (1..1000).each do |i| puts i sleep 1 end rescue Exception => b puts "\nCaught exception..." puts "Exception class: #{b.class}" end 

What are "Exception" and "=>"? Is there another way to write this expression to make it more intelligible from a syntactical point of view? I don't think we're dealing with a hash here because the following code compiles but throws an error as soon as CTRL+C is pressed (undefined local variable or method `e').

begin (1..1000).each do |i| puts i sleep 1 end rescue { Exception => b } puts "\nCaught exception..." puts "Exception class: #{b.class}" end 

Can someone explain what is going on? and specifically what language element '=>' (hashrocket) is in this specific example since it seems to have nothing to do with hashes?

1 Answer 1

11

I'm sorry to inform you that this is just one-off syntax that doesn't really have any relation to other Ruby syntax.

Given the expression:

begin # ... rescue FooError, BarError => ex # ... end 
  • FooError, BarError is the list of exception classes (usually subclasses of StandardError) that will be rescued. This behaves just like an argument list, so you can (if you want) do stuff like this:

    my_exception_classes = [ FooError, BarError ] begin # ... rescue *my_exception_classes => ex # ... end 

    It's worth noting that you shouldn't, generally, use Exception here because it will rescue all exceptions, including things like SignalException::Interrupt and NoMemoryError, which usually isn't what you want.

  • => is just syntax, and arguably not the best choice of syntax for the reason that it leads to questions like your own.

  • ex is the name of a local variable into which the exception object will be put.

Digging deeper

If you're into reading parser grammars, it's always fun looking at Ruby's YACC grammar in parse.y. It's not especially easy to read, but we can see the grammar for a rescue expression, called opt_rescue in the grammar, here:

opt_rescue : k_rescue exc_list exc_var then compstmt opt_rescue 

k_rescue is of course the keyword rescue. exc_list is the list of exception classes which, like I said, is just like an argument list:

exc_list : arg_value 

exc_var is the part where the variable to put the exception in is designated:

exc_var : tASSOC lhs 

And here, tASSOC is of course our friend the hashrocket (=>), and lhs, i.e. “left-hand side,” is an expression you'd find to the left of an assignment expression (like, say, the name of a variable).

compstmt is basically “any valid Ruby code,” and then there’s opt_rescue again, since you can (optionally) have many rescues in a begin or def block.

As you can see, the only thing this syntax has in common with a Hash is tASSOC.

Sign up to request clarification or add additional context in comments.

3 Comments

If you put something else in place of the class list you get an illuminating error e.g. rescue 2 => ex gives "class or module required for rescue clause". You would get the same error with { Exception => b } if b were defined, because it's a hash.
Thank you very much for the concise explanation. I once wrote a recursive descent compiler for a language I invented for a 4 bit computer I built in digital design class years ago. It's been a long long time, but the whole grammar discussion is not foreign to me. This helps a lot.
Thank you for the syntax breakdown and pointers to how to read it

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.