From 0bd976aeb3a3fefb89bcfd0ea833422dee9d21cb Mon Sep 17 00:00:00 2001 From: jbranchaud Date: Tue, 29 Dec 2020 18:05:44 -0600 Subject: [PATCH] Add Jump Out Of A Nested Context With Throw/Catch as a Ruby til --- README.md | 3 +- ...ut-of-a-nested-context-with-throw-catch.md | 38 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 ruby/jump-out-of-a-nested-context-with-throw-catch.md diff --git a/README.md b/README.md index 6026dae..a2a84a7 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ pairing with smart people at Hashrocket. For a steady stream of TILs, [sign up for my newsletter](https://tinyletter.com/jbranchaud). -_986 TILs and counting..._ +_987 TILs and counting..._ --- @@ -804,6 +804,7 @@ _986 TILs and counting..._ - [Iterate With An Offset Index](ruby/iterate-with-an-offset-index.md) - [Ins And Outs Of Pry](ruby/ins-and-outs-of-pry.md) - [Invoking Rake Tasks Multiple Times](ruby/invoking-rake-tasks-multiple-times.md) +- [Jump Out Of A Nested Context With Throw/Catch](ruby/jump-out-of-a-nested-context-with-throw-catch.md) - [Last Raised Exception In The Call Stack](ruby/last-raised-exception-in-the-call-stack.md) - [Limit Split](ruby/limit-split.md) - [Listing Local Variables](ruby/listing-local-variables.md) diff --git a/ruby/jump-out-of-a-nested-context-with-throw-catch.md b/ruby/jump-out-of-a-nested-context-with-throw-catch.md new file mode 100644 index 0000000..86abe28 --- /dev/null +++ b/ruby/jump-out-of-a-nested-context-with-throw-catch.md @@ -0,0 +1,38 @@ +# Jump Out Of A Nested Context With Throw/Catch + +Ruby's `throw/catch` construct, not to be confused with its `raise/rescue` +exception handling syntax, allows you to jump out of a nested context. This is +similar to [loop +labels](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label) +in other languages. + +For example, in my recent [Advent of Code +solution](https://www.youtube.com/watch?v=Hvp07gTQhF4), I was able to employ +this construct. Once within a doubly-nested loop, I can `throw` when I find the +answer I'm looking for to both break out of the loop and return an value. + +```ruby +answer = + catch do |obj| + input.each_with_index do |input1, x| + input.each_with_index do |input2, y| + next unless x != y + + next unless input1 + input2 == 2020 + + throw(obj, input1 * input2) + end + end + + raise StandardError, 'No answer found' + end + +puts answer +``` + +If I were to never reach the `throw` before exhausting the doubly-nested loop, +then the catch would product whatever value is returned within the block. In +this case, I raise an error because it'd be exceptional for the `throw` to +never be reached. + +[source](https://apidock.com/ruby/Kernel/catch)