Roman
Roman

Reputation: 10403

In Ruby what is the difference between different rescue statements?

In Ruby what is the difference between

def run
 begin
   raise SomeError.new
 rescue SomeError
   handle
 end    
end

and

def run
  raise SomeError.new
rescue SomeError
  handle
end

Upvotes: 1

Views: 399

Answers (7)

Gagan Gami
Gagan Gami

Reputation: 10251

Example:

begin
  # something which might raise an exception
rescue SomeExceptionClass => some_variable
  # code that deals with some exception
ensure
  # ensure that this code always runs
end

Here, def as a begin statement:

def
  # something which might raise an exception
rescue SomeExceptionClass => some_variable
  # code that deals with some exception
ensure
  # ensure that this code always runs
end

Basically there is no difference. In above code method def can serve as a begin statement:

As spickermann commented You can also use else that is only run if there wasn't an expection

begin  
  # -  
rescue OneTypeOfException  
  # -  
rescue AnotherTypeOfException  
  # -  
else  
  # Other exceptions  
end

For each rescue clause in the begin block, Ruby compares the raised Exception against each of the parameters in turn. The match will succeed if the exception named in the rescue clause is the same as the type of the currently thrown exception, or is a superclass of that exception. The code in an else clause is executed if the code in the body of the begin statement runs to completion without exceptions. If an exception occurs, then the else clause will obviously not be executed.

Refer this for more understanding: http://rubylearning.com/satishtalim/ruby_exceptions.html

Upvotes: 1

SWagh
SWagh

Reputation: 47

IT looks both are same. In second code it gives you more code.

Upvotes: 0

Amadan
Amadan

Reputation: 198436

They are equivalent, even if they do not generate identical code. Most of the changes are just renumberings, but there are a couple of extra instructions in the first one (labeled by - in this unified diff). They do not do much though (mainly trace and labels).

 ["YARVInstructionSequence/SimpleDataFormat", 2, 2, 1,
  {:arg_size=>0, :local_size=>1, :stack_max=>4},
  "<compiled>", "<compiled>", nil, 1, :top, [], {}, [],
  [1,
   [:trace, 1],
   [:putspecialobject, 1],
   [:putspecialobject, 2],
   [:putobject, :run],
   [:putiseq,
    ["YARVInstructionSequence/SimpleDataFormat", 2, 2, 1,
     {:arg_size=>0, :local_size=>1, :stack_max=>2},
     "run", "<compiled>", nil, 1, :method, [], {},
     [[:rescue,
       ["YARVInstructionSequence/SimpleDataFormat", 2, 2, 1,
        {:arg_size=>0, :local_size=>2, :stack_max=>2},
        "rescue in run", "<compiled>", nil, 2, :rescue, [:"\#$!"], {}, [],
-       [4,
-        [:trace, 1],
+       [3,
         [:getlocal_OP__WC__0, 2],
-        [:getinlinecache, :label_11, 0],
+        [:getinlinecache, :label_9, 0],
         [:getconstant, :SomeError],
         [:setinlinecache, 0],
-        :label_11,
+        :label_9,
         [:checkmatch, 3],
-        [:branchunless, :label_21],
-        5,
+        [:branchunless, :label_19],
+        4,
         [:trace, 1],
         [:putself],
         [:opt_send_without_block, {:mid=>:handle, :flag=>280, :blockptr=>nil, :orig_argc=>0}],
-        4,
+        3,
         [:leave],
-        :label_21,
+        :label_19,
         0,
         [:getlocal_OP__WC__0, 2],
         [:throw, 0]]],
-      :label_4,
-      :label_18,
-      :label_19,
+      :label_2,
+      :label_16,
+      :label_17,
       0],
-     [:retry, nil, :label_18, :label_19, :label_4, 0]],
+     [:retry, nil, :label_16, :label_17, :label_2, 0]],
     [1,
      [:trace, 8],
+     :label_2,
      2,
      [:trace, 1],
-     :label_4,
-     3,
-     [:trace, 1],
      [:putself],
-     [:getinlinecache, :label_14, 0],
+     [:getinlinecache, :label_12, 0],
      [:getconstant, :SomeError],
      [:setinlinecache, 0],
-     :label_14,
+     :label_12,
      [:opt_send_without_block, {:mid=>:new, :flag=>256, :blockptr=>nil, :orig_argc=>0}],
      [:opt_send_without_block, {:mid=>:raise, :flag=>264, :blockptr=>nil, :orig_argc=>1}],
-     :label_18,
-     2,
+     :label_16,
      [:nop],
-     :label_19,
-     7,
+     :label_17,
+     5,
      [:trace, 16],
-     3,
+     2,
      [:leave]]]],
   [:opt_send_without_block,
    {:mid=>:"core#define_method", :flag=>256, :blockptr=>nil, :orig_argc=>3}],
   [:leave]]]

Upvotes: 1

jvnill
jvnill

Reputation: 29599

There is no difference between the 2 code you asked. The only time you'd like to use begin though is if you only want a certain part of your code to be rescued.

def rescue_me
  no_rescue = 1 + 1

  begin
    no_rescue / 0
  rescue
    # handle
  end
end

It's also a good reminder to not just use rescue. You should have an idea of what exception you want to rescue. In the example above, you'd want to rescue ZeroDivisionError.

Upvotes: 1

maximus ツ
maximus ツ

Reputation: 8065

Both are same things with different syntax. Later is used to rescue a whole method instead of code block.

Upvotes: 0

bbozo
bbozo

Reputation: 7311

In this specific case, there is no difference except that option 1 looks uglier,

rescue applies to a code context, by placing a begin...end you create a code context to which rescue applies,

the second option works is because a method def...end is a code context too

Upvotes: 0

pangpang
pangpang

Reputation: 8821

The are same, no difference. The second is the shorthand of the first.

Upvotes: 1

Related Questions