Where Are Catch and Throw Useful in Ruby

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



Leave a reply



Submit