Differencebetween Raising Exceptions VS Throwing Exceptions in Ruby

What is the difference between Raising Exceptions vs Throwing Exceptions in Ruby?

I think http://hasno.info/ruby-gotchas-and-caveats has a decent explanation of the difference:

catch/throw are not the same as raise/rescue. catch/throw allows you to quickly exit blocks back to a point where a catch is defined for a specific symbol, raise rescue is the real exception handling stuff involving the Exception object.

What is the difference between `raise foo ` and `raise Exception.new( foo )`?

Technically, the first raises a RuntimeError with the message set to "foo", and the second raises an Exception with the message set to "foo".

Practically, there is a significant difference between when you would want to use the former and when you want to use the latter.

Simply put, you probably want a RuntimeError not an Exception. A rescue block without an argument will catch RuntimeErrors, but will NOT catch Exceptions. So if you raise an Exception in your code, this code will not catch it:

begin
rescue
end

In order to catch the Exception you will have to do this:

begin
rescue Exception
end

This means that in a sense, an Exception is a "worse" error than a RuntimeError, because you have to do more work to recover from it.

So which you want depends on how your project does its error handling. For instance, in our daemons, the main loop has a blank rescue which will catch RuntimeErrors, report them, and then continue. But in one or two circumstances, we want the daemon to really really die on an error, and in that case we raise an Exception, which goes straight through our "normal error handling code" and out.

And again, if you are writing library code, you probably want a RuntimeError, not an Exception, as users of your library will be surprised if it raises errors that a blank rescue block can't catch, and it will take them a moment to realize why.

Finally, I should say that the RuntimeError is a subclass of the StandardError class, and the actual rule is that although you can raise any type of object, the blank rescue will by default only catch anything that inherits from StandardError. Everything else has to be specific.

C#: Do you raise or throw an exception?

In C# terminology, raising is used in the context of events and throwing is used in the context of exceptions.

Personally, I think throw/catch combination is more beautiful than raise/catch.

Raising an exception: use instance or class?

It makes no difference; the exception class will be instiantiated in either case.

If you provide a string, either as the argument to new or as the second argument to raise, it be passed to initialize and will become the exception instance's .message.

For example:

class GoatException < StandardError
def initialize(message)
puts "initializing with message: #{message}"
super
end
end

begin
raise GoatException.new "Goats do not enjoy origami." #--|
# | Equivilents
raise GoatException, "Goats do not enjoy origami." #--|
rescue Exception => e
puts "Goat exception! The class is '#{e.class}'. Message is '#{e.message}'"
end

If you comment the first raise above, you'll see that:

  • In both cases, initialize is called.
  • In both cases, the exception class is GoatException, not class as it would be if we were rescuing the exception class itself.

In Ruby what is the difference between different rescue statements?

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

Fail vs. raise in Ruby : Should we really believe the style guide?

use 'raise' for exceptions to be caught, and 'fail' for serious errors which are not meant to be handled

This is not what the official style guide or the link you provided say on the matter.

What is meant here is use raise only in rescue blocks. Aka use fail when you want to say something is failing and use raise when rethrowing an exception.

As for the "does it matter" part - it is not one of the most hardcore strictly followed rules, but you could make the same argument for any convention. You should follow in that order:

  1. Your project style guide
  2. Your company style guide
  3. The community style guide

Ideally, the three should be the same.


Update: As of this PR (December 2015), the convention is to always use raise.

ruby catch-throw and efficiency

In addition to being the "correct" way to get out of control structures, catch-throw is also significantly faster(10 times as fast in my testing). Check out this gist for my code and results.

What's the difference between raise, try, and assert?

Assert:

Used when you want to "stop" the script based on a certain condition and return something to help debug faster:

list_ = ["a","b","x"]
assert "x" in list_, "x is not in the list"
print("passed")
#>> prints passed

list_ = ["a","b","c"]
assert "x" in list_, "x is not in the list"
print("passed")
#>>
Traceback (most recent call last):
File "python", line 2, in <module>
AssertionError: x is not in the list

Raise:

Two reasons where this is useful:

1/ To be used with try and except blocks. Raise an error of your choosing, could be custom like below and doesn't stop the script if you pass or continue the script; or can be predefined errors raise ValueError()

class Custom_error(BaseException):
pass

try:
print("hello")
raise Custom_error
print("world")
except Custom_error:
print("found it not stopping now")

print("im outside")

>> hello
>> found it not stopping now
>> im outside

Noticed it didn't stop? We can stop it using just exit(1) in the except block.

2/ Raise can also be used to re-raise the current error to pass it up the stack to see if something else can handle it.

except SomeError, e:
if not can_handle(e):
raise
someone_take_care_of_it(e)

Try/Except blocks:

Does exactly what you think, tries something if an error comes up you catch it and deal with it however you like. No example since there's one above.

Why is it better to throw an exception rather than return an error code?

I've written about this at length: Exceptions vs. status returns, but briefly:

  1. Exceptions leaves your code clean of all the checks necessary when testing status returns on every call,
  2. Exceptions let you use the return value of functions for actual values,
  3. Exceptions can carry more information than a status return can,
  4. Most importantly: exceptions can't be ignored through inaction, while status returns can.

To expand on the last point: if you forget to do what you should be doing with status returns, you ignore errors. If you forget to do what you should be doing with exceptions, the exception bubbles up to the outer layer of the software where it becomes visible.



Related Topics



Leave a reply



Submit