DEV Community

loading...

A silly thing you can do with the Ruby parser

penelope_zone profile image Penelope Phippen Originally published at penelope.zone Updated on ・2 min read

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"

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

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>}

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"

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.

Discussion

pic
Editor guide
Collapse
dkassen profile image
Daniel Kassen

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