I tried this earlier and everyone got off on rescue block syntax. Please don't go there. Given the following working code:
begin
(1..1000).each do |i|
puts i
sleep 1
end
rescue Exception => e
puts "\nCaught exception..."
puts "Exception class: #{e.class}"
end
Pressing CTRL+C while it is running prints out "Caught exception...", as expected. What exactly is going on syntax wise in the rescue line, particularly between Exception
and the variable e
with the =>
in between?
The word "rescue" is a keyword... part of the ruby language. "e" is a variable, and could just as functionally be "a", "b", or "c". The following code works just as well.
begin
(1..1000).each do |i|
puts i
sleep 1
end
rescue Exception => b
puts "\nCaught exception..."
puts "Exception class: #{b.class}"
end
What are "Exception" and "=>"? Is there another way to write this expression to make it more intelligible from a syntactical point of view? I don't think we're dealing with a hash here because the following code compiles but throws an error as soon as CTRL+C is pressed (undefined local variable or method `e').
begin
(1..1000).each do |i|
puts i
sleep 1
end
rescue { Exception => b }
puts "\nCaught exception..."
puts "Exception class: #{b.class}"
end
Can someone explain what is going on? and specifically what language element '=>' (hashrocket) is in this specific example since it seems to have nothing to do with hashes?
I'm sorry to inform you that this is just one-off syntax that doesn't really have any relation to other Ruby syntax.
Given the expression:
begin
# ...
rescue FooError, BarError => ex
# ...
end
FooError, BarError
is the list of exception classes (usually subclasses of StandardError
) that will be rescued. This behaves just like an argument list, so you can (if you want) do stuff like this:
my_exception_classes = [ FooError, BarError ]
begin
# ...
rescue *my_exception_classes => ex
# ...
end
It's worth noting that you shouldn't, generally, use Exception
here because it will rescue all exceptions, including things like SignalException::Interrupt
and NoMemoryError
, which usually isn't what you want.
=>
is just syntax, and arguably not the best choice of syntax for the reason that it leads to questions like your own.
ex
is the name of a local variable into which the exception object will be put.
If you're into reading parser grammars, it's always fun looking at Ruby's YACC grammar in parse.y
. It's not especially easy to read, but we can see the grammar for a rescue
expression, called opt_rescue
in the grammar, here:
opt_rescue : k_rescue exc_list exc_var then
compstmt
opt_rescue
k_rescue
is of course the keyword rescue
. exc_list
is the list of exception classes which, like I said, is just like an argument list:
exc_list : arg_value
exc_var
is the part where the variable to put the exception in is designated:
exc_var : tASSOC lhs
And here, tASSOC
is of course our friend the hashrocket (=>
), and lhs
, i.e. “left-hand side,” is an expression you'd find to the left of an assignment expression (like, say, the name of a variable).
compstmt
is basically “any valid Ruby code,” and then there’s opt_rescue
again, since you can (optionally) have many rescues
in a begin
or def
block.
As you can see, the only thing this syntax has in common with a Hash is tASSOC
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With