What is catch and throw used for in Ruby?
You can use this to break out of nested loops.
INFINITY = 1.0 / 0.0
catch (:done) do
1.upto(INFINITY) do |i|
1.upto(INFINITY) do |j|
if some_condition
throw :done
end
end
end
end
If you had used a break statement above, it would have broken out of the inner loop. But if you want to break out of the nested loop, then this catch/throw would be really helpful. I have used it here to solve one of the Euler problems.
Where are catch and throw useful in Ruby?
Note: It looks like a few things have changed with catch/throw in 1.9. This answer applies to Ruby 1.9.
A big difference is that you can throw
anything, not just things that are derived from StandardError
, unlike raise
. Something silly like this is legal, for example:
throw Customer.new
but it's not terribly meaningful. But you can't do:
irb(main):003:0> raise Customer.new
TypeError: exception class/object expected
from (irb):3:in `raise'
from (irb):3
from /usr/local/bin/irb:12:in `<main>'
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.
How to determine which call to throw is caught in a catch block?
[...] is it possible to figure out which throw actually run? [...] The question is inspired by debugging a warden gem
For debugging purposes, Ruby provides Tracepoint
.
In Ruby terms, Kernel::throw
is an ordinary method written in C. To see which one was called, you could use:
TracePoint.trace(:c_call) do |tp|
printf("%s:%d\n", tp.path, tp.lineno) if tp.method_id == :throw
end
The above code will print the file path and line number each time a C method with the name throw
is called.
Ruby Throw-Catch tutorial unclear
That final line promptAndGet("Name")
does not get immediately executed, since it's after the catch
block.
The normal flow is that everything within the catch :quitRequested
block gets executed immediately, in order. That's why you get all 3 prompts inside. If you answer all 3 prompts, you'll also get to the prompt on the last line.
If you answer !
to any of the three prompts, the block will terminate. So you will not get the remaining prompts inside the block.
You'll still get the prompt on the last line since it's outside of the catch
.
throw
is what terminates the catch
block - not what initiates it.
Also, if you answer !
to that final prompt outside of the catch
block, you'll get an error, because the throw
was uncaught.
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.
Related Topics
Calling Instance Variables Without @
Ruby Multiple Background Threads
Brew Install Coreutils Failing 10.9.5 Osx
Ruby on Rails: Create Confirmation View Before Creating the Object
Ruby - Convert Integer to String
When Is the Do Keyword Required in Ruby
Can Anyone Explain This Array Declaration to Me
Jekyll Liquid - Accessing _Config.Yml Dynamically
Ruby: Calculate Time Difference Between 2 Times
Rational - Original Numbers in Ruby
How to Create an Association Between Two Rails Models
How to Add Iedriverserver to Path
How to Stop Bundler from Adding Ruby Version to Gemfile.Lock
Change Emacs Ruby-Mode Indent to 4 Spaces
Why Doesn't Array Override the Triple Equal Sign Method in Ruby
How to Create a "Clone"-Able Enumerator for External Iteration