Monday, December 27, 2010

Patrick Farley on Ruby Internals

Elegance in Action
Enlightening talk on how Ruby handles class hierarchies:
http://mwrc2008.confreaks.com/11farley.html
Patrick reveals an important simplicity: method dispatch happens the same way, all the time.
"Elegance is the simplicity found on the far side of complexity" [1]
That is: you find a mathematical beauty from slogging your way through the various details and extracting from that an essential common concept.

Back to Farley... just two data structures and then this simplifying singular algorithm for method dispatch.  Simplistically:

  • A Ruby object has two primary data members: its values for its instance variables and a pointer to its type (what class it is)
  • Ruby class is has two distinguishing data members: a list of methods and a pointer to its super class.

here's the algorithm for method dispatch:

  1. for the object being send the "message"/"method call", dereference its Class
  2. look for the method in that Class' list of methods.  If found, you're done; otherwise continue.
  3. dereference this Class' super class and repeat step 2 (unless you're already at the "Object" class, in that case, you've got the "method_missing" event.

Given this algorithm, you can understand how Ruby implements:
  • per-instance methods ("plain ol'" singleton class)
  • class methods (a metaclass)
  • include class (a singleton class created for each time the module is included)

Per-Instance Methods

These are methods added not to a class, but to an object:
1  class Foo
2   def defined_in_the_class
3     puts "Foo you!"
4   end
5  end
6
7  bar = Foo.new
8  baz = Foo.new
9  
10 def bar.only_works_on_bar
11   puts "I'm a bar!"
12 end
13
14 bar.only_works_on_bar
15 baz.only_works_on_bar
which outputs:
I'm a bar!
NoMethodError: undefined method `only_works_on_bar' for #
from (irb):15
from :0

On line 10, under the covers, Ruby is actually creating a secret class, known as a singleton class.  I'll follow Farley's example and use the prime notation: Foo'.  Foo' is the actual direct class of the object "bar".  Foo' 's super class is Foo.

That secret class creation occurs only on the first time a method is defined on an object.  It's the "purest" form of a "singleton class" -- it's a class which will only ever have one instance (here, Foo' has exactly on instance... that referenced by "bar").

Class Methods

It turns out, that each time you define a class, Ruby actually creates the object that is the class AND a "metaclass" (which is the singleton class of that object).
class Foo
  def self.im_a_class_method
    puts "this impl is stored in Foo's metaclass"
  end
end
Here, we are defining a class, Foo.  An object (of type "Class") is created and given the name of "Foo".  That instance of Class is immediately given a singleton class whereon class methods will be stored.  Remember, a class is an object (an instance of Class) and therefore, this is just per-instance behavior of instances of Class.  It's literally the exact same mechanism providing both class methods and per-instance method behavior.


[1] - http://www.amazon.com/dp/0743290178

No comments: