Last week Pat Shaughnessy discovered that there’s a pre-processor definition in the Ruby 1.9 source code to enable goto and label statements in a rather ugly way:
The
__goto__statement will cause the MRI Ruby 1.9 interpreter to jump up to the__label__statement on the first line, since they both refer to the same symbol:loop.
I don’t think there’s much use for goto in a language like Ruby
considering that it’s garbage collected and you can release resources
using closures and ensure blocks. However, if you’re dying to play
with this, why not use goto’s little brother, catch and throw:
class Test
def foo
throw(:label, "foo")
"should never get here"
end
def bar
"bar"
end
end
test = Test.new
puts("foo -> " + catch(:label) {test.foo})
puts("bar -> " + catch(:label) {test.bar})
There’s not much to know about catch and throw. You give a symbol
and a block to catch, which acts like a goto label. Any code that
uses throw in that block, no matter how deep, will unwind and cause
the catch block to terminate, returning the value given to throw.
You can nest multiple catch and throw expressions using different
values for the label symbol. Here’s another example:
def thrower
10.times do |i|
10.times do |j|
$stdout.puts("#{i}.#{j}")
throw(:label, j) if i > 2 and j > 2
end
end
end
val = catch(:label) do
thrower
raise("should never get here")
end
$stdout.puts("val is #{val}")