Munish
Munish

Reputation: 988

Understanding syntax of the statement "rescue ErrorType1, ErrorType2 => ex"

A quick query: How would a Java programmer will understand the following Ruby statement:

rescue ErrorType1, ErrorType2 => ex

That is, I want to put brackets/parenthesis around it explicitly. So, is it?

rescue(ErrorType1, {ErrorType2 => ex})

or,

rescue({[ErrorType1, ErrorType2] => ex})

or, something else...

Upvotes: 2

Views: 202

Answers (3)

Ranjan
Ranjan

Reputation: 56

About the syntax:

rescue ErrorType1, ErrorType2 => ex

Please note following:

  1. There is no hash involved
  2. 'rescue' is not a method, you can't even write it as rescue(ErrorType1, ErrorType2 => ex)
  3. Ruby places a reference to raised associated exception into the global variable $!.
  4. In the above form, the 'rescue' takes a special argument where you give the name of a local variable to receive the matched exception, which is more readable then using $!.

Now, look at the syntax again...

Upvotes: 4

Arup Rakshit
Arup Rakshit

Reputation: 118289

Look at the below code :

begin
    a=1/0
rescue => e
    p e.class
    p defined?(e)
end
# >> ZeroDivisionError
# >> "local-variable"

Where e is a local variable to that exception handling block. In Ruby local variables are created using assignment operation,but in case of exception handling,reference to the currently raised exception is assigned to the local variable e using the hash rocket(=>),instead of =. This is as per design. Don't think of that it is a Hash.

In Ruby we use one or more rescue clauses to tell Ruby the types of exceptions we want to handle.If you write a rescue clause with no parameter list, the parameter defaults to StandardError. Each rescue clause can specify multiple exceptions to catch. At the end of each rescue clause you can give Ruby the name of a local variable to receive the matched exception. The parameters to the rescue clause can also be arbitrary expressions (including method calls) that return an Exception class. If we use raise with no parameters, it re-raises the exception.Handling an Exception

Out of three of your codes only valid is rescue ErrorType1, ErrorType2 => ex. Others will give you syntax error.

Hierarchy(partial) :

StandardError
   |
  IndexError
      |
     KeyError

You can specify the error class names as arguments to the rescue list,in any order.On runtime ruby will pick up the correct one from the list. Look the code below :

begin
    a = {}
    a.fetch(:b)
rescue StandardError,KeyError,IndexError => e
    p e.class
end
# >> KeyError

begin
    a = {}
    a.fetch(:b)
rescue KeyError,StandardError,IndexError => e
    p e.class
end
# >> KeyError

If you think,you would tell Ruby interpreter on runtime, which one to match first using paren from the argument list,Ruby will not allow you to do so,in return it will throw to you syntax error. Same also for below :

begin
    a = {}
    a.fetch(:b)
rescue StandardError => e1
    p e1.class
rescue IndexError => e2
    p e2.class
rescue KeyError => e3
    p e3.class
end
# >> KeyError

Note: If we want to catch more exception classes, we can just write them in line. When we want to handle different errors differently, we can specify several rescue clauses.Ruby Hacking Guide

Upvotes: 1

Agis
Agis

Reputation: 33646

rescue is a control structure with it's own syntax, it's not a method call, so your 2nd and 3rd code blocks are invalid syntax, you aren't not passing any arguments.

rescue <exception-class1>[, <exception-class2>] => <a variable to assign the exception to>

so when doing rescue TypeError, StandardError => my_exception it will catch any TypeError or StandardError exception that is raised and assign it to the my_exception local variable.

I suggest the recently translated Ruby Hacking Guide (search for "rescue").

Upvotes: 2

Related Questions