except is how you handle an exception that some other code signalled. raise is how you signal an exception yourself. It's like asking what the difference is between making a phone call and answering the phone. In except you usually handle exceptions, you normally don't raise other exceptions.
Raising an exception is a technique for interrupting the normal flow of execution in a program, signaling that some exceptional circumstance has arisen, and returning directly to an enclosing part of the program that was designated to react to that circumstance.
Ruby actually gives you the power to manually raise exceptions yourself by calling Kernel#raise. This allows you to choose what type of exception to raise and even set your own error message. If you do not specify what type of exception to raise, Ruby will default to RuntimeError (a subclass of StandardError ).
raise is a keyword in Ruby which allows us to raise any exception if it found, raise will throw an exception and that exception will be caught inside the rescue statement. Syntax: Web development, programming languages, Software testing & others. Below is the simple syntax for the raise statement in Ruby.
raise
, fail
, rescue
, and ensure
handle errors, also known as exceptions
throw
and catch
are control flow
Unlike in other languages, Ruby’s throw and catch are not used for exceptions. Instead, they provide a way to terminate execution early when no further work is needed. (Grimm, 2011)
Terminating a single level of control flow, like a while
loop, can be done with a simple return
. Terminating many levels of control flow, like a nested loop, can be done with throw
.
While the exception mechanism of raise and rescue is great for abandoning execution when things go wrong, it's sometimes nice to be able to jump out of some deeply nested construct during normal processing. This is where catch and throw come in handy. (Thomas and Hunt, 2001)
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.
https://coderwall.com/p/lhkkug/don-t-confuse-ruby-s-throw-statement-with-raise offers an excellent explanation that I doubt I can improve on. To summarize, nicking some code samples from the blog post as I go:
raise
/rescue
are the closest analogues to the throw
/catch
construct you're familiar with from other languages (or to Python's raise
/except
). If you've encountered an error condition and you would throw
over it in another language, you should raise
in Ruby.
Ruby's throw
/catch
lets you break execution and climb up the stack looking for a catch
(like raise
/rescue
does), but isn't really meant for error conditions. It should be used rarely, and is there just for when the "walk up the stack until you find a corresponding catch
" behaviour makes sense for an algorithm you're writing but it wouldn't make sense to think of the throw
as corresponding to an error condition.
What is catch and throw used for in Ruby? offers some suggestions on nice uses of the throw
/catch
construct.
The concrete behavioural differences between them include:
rescue Foo
will rescue instances of Foo
including subclasses of Foo
. catch(foo)
will only catch the same object, Foo
. Not only can you not pass catch
a class name to catch instances of it, but it won't even do equality comparisons. For instance
catch("foo") do
throw "foo"
end
will give you an UncaughtThrowError: uncaught throw "foo"
(or an ArgumentError
in versions of Ruby prior to 2.2)
Multiple rescue clauses can be listed...
begin
do_something_error_prone
rescue AParticularKindOfError
# Insert heroism here.
rescue
write_to_error_log
raise
end
while multiple catch
es need to be nested...
catch :foo do
catch :bar do
do_something_that_can_throw_foo_or_bar
end
end
A bare rescue
is equivalent to rescue StandardError
and is an idiomatic construct. A "bare catch
", like catch() {throw :foo}
, will never catch anything and shouldn't be used.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With