One of the concept I had to get used to moving from Python to Ruby was that regular objects aren’t callable, and that there was a closed set of objects that can be called. Meaning that where in Python it was possible for any class to implement call and so allow us to call it with obj(), Ruby doesn’t allow this. One of the advantages of that syntax in Python is that each class implements its constructor using this. For example:

class MyClass: def __init__(self, value): self.value = value my_class = MyClass(1) # We are calling the class to get # an instance, instead of # MyClass.new(1) in Ruby

This was a nice little trick I liked in Python but quickly got used to living without it. That was until I saw Ruby code that seemed to allow the exact same behavior:

Integer.class #=> Class Integer(1) #=> 1

How’s this so? Can we really make classes callable? A quick glance at Integer’s source code in the Rubinius code reveals that there’s no magic going on in it, and that it actually has no reference for this method I’m looking to call. Instead what we’ll see is that alongside the class definition there’s also a method definition:

class Integer #... end def Integer(value) #... end

So the whole trick is simply to define both. But how exactly does this work? How are names not clashing?

What actually happens is that whenever we define a new class or module, its name is added as a constant that points to the actual class. Similarly, when we define a method at the top level it’s added as a private method to Object. That means that whenever we type in a name that looks like a constant (starts with a capital letter) without parenthesis, Ruby will search for that constant:

Object.const_defined? :Integer #=> true

But when we add parenthesis, Ruby understands that it should seek for a method instead:

Object.private_method_defined? :Integer #=> true

This nifty little trick is all it takes for Ruby to allow this nice syntax.

Hope you learned a new thing! In case you want to dig deeper, two great books that really helped me wrap my head around dark corners of Ruby are Eloquent Ruby and Metaprogramming Ruby.

You should subscribe to my feed and follow me on twitter!