7

catch in Ruby is meant to jump out of deeply nested code. In Java e.g. it is possible to achieve the same with Java's try-catch meant for handling exceptions, it is however considered poor solution and is also very inefficient. In Ruby for handling exceptions we have begin-raise-rescue and I assume it is also to expensive to use it for other tasks.

Is Ruby's catch-throw really a more efficient solution then begin-raise-rescue or are there any other reasons to use it to break nested blocks instead of begin-raise-rescue?

Josh
  • 5,631
  • 1
  • 28
  • 54
wrzasa
  • 1,113
  • 10
  • 20
  • If you post some ruby examples of the control structures you are asking about, it may be more clear what you mean. – Alex Wayne Nov 20 '12 at 23:59

2 Answers2

9

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.

Josh
  • 5,631
  • 1
  • 28
  • 54
  • Thanks! The benchmark really clears the issue (in my case it is almost 15 times!). Should catch-throw be considered a structural style of programing -- a better practice then despised goto? – wrzasa Nov 21 '12 at 09:23
  • It's your design requires catch-throw, there is probably a better design. That being said, there are definitely edge cases where catch throw make a lot of sense, especially in gem develop where you don't know how the end user will use it. – Josh Nov 22 '12 at 15:32
  • Thanks for all explanations! – wrzasa Nov 23 '12 at 10:53
8

Josh's answer is correct. I want to add more information about catch-throw and raise-rescue.

catch-throw is used for flow control whereas raise-rescue is used for exception/error handling. The different is: backtrace is not needed for catch-throw (flow control). Trust me, the main reason causes raise-rescue runs slow than catch-throw 10 times in Josh's gist is raise-rescue takes a lot time to create backtrace object.

If you want to raise without backtrace, use syntax:

raise <type>, <message>, <backtrace>

Checkout my gist. raise without backtrace is much faster than raise with backtrace.

April 2016 Update:

I've updated my gist:

  • Fixed "break" test
  • Added benchmark tests results for newer ruby version 2.1.8, 2.2.4, 2.3.0
Community
  • 1
  • 1
Jacob Dam
  • 2,278
  • 18
  • 18