DEV Community

Penelope Phippen
Penelope Phippen

Posted on • Edited on • Originally published at penelope.zone

A silly thing you can do with the Ruby parser

Here's a silly thing you can do with the Ruby parser:

begin
  raise "omg"
rescue =>
  (class Box
   class << self
     attr_accessor :contents
   end
end; Box).contents
end

puts Box.contents

# => "omg"
Enter fullscreen mode Exit fullscreen mode

You... what?

So let's break this down. In Ruby, the way one catches exceptions is with a
begin...rescue...end expression. The rescue part of that looks like this:
rescue <class_name> => <assignable_expression>. Usually you'd see something
like:

begin
 ... whatever
rescue SomeClass => some_local_variable_name
  do_something_with_local_variable(some_local_variable_name)
end
Enter fullscreen mode Exit fullscreen mode

However, it doesn't have to be this way. In fact, the Ruby parser permits any
valid assignment expression in Ruby! So we can for example set a key in a hash
from a rescue:

h = {}
begin
  raise "omg"
rescue => h[:the_key]
end

puts h.inspect
# => {:the_key=>#<RuntimeError: omg>}
Enter fullscreen mode Exit fullscreen mode

So, to come back to our first example:

begin
  raise "omg"
rescue =>
  (class Box
   class << self
     attr_accessor :contents
   end
end; Box).contents
end

puts Box.contents

# => "omg"
Enter fullscreen mode Exit fullscreen mode

Here we, in the rescue clause, define a class called box, define a class
level attribute called contents, and then set it. You shouldn't ever do this in
you production code, but it is possible.

Why is this even possible?

As far as I can tell, the reason why this works as it does has to do with the
history of the implementation of Ruby. Before Ruby 1.9, Ruby used a "tree
walking" interpreter. This means that Ruby code was executed from the syntax
tree of the program, with no intermediate steps. Putting the rescued exception
"somewhere", conceptually, is the same thing as variable assignment, even though
it doesn't look like local_name =, so the code was shared between rescue and
variable assignment.

Neat!

If you enjoyed this post, please consider sending me a follow on twitter:
@penelope_zone.

Top comments (1)

Collapse
 
dkassen profile image
Daniel Kassen

Thanks for sharing! This is awesome and I’d love to see more.