Reputation: 10403
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
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
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
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
Reputation: 8065
Both are same things with different syntax. Later is used to rescue a whole method instead of code block.
Upvotes: 0
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
Reputation: 8821
The are same, no difference. The second is the shorthand of the first.
Upvotes: 1