Feb 24 2009

Ruby’s Eigenclass and Metaclass

If you are like me, you have probably dabbled in Ruby meta-programming, but never really found a place to use it, so never got very far. While we all love _why’s unique writing, his article on meta-programming was a bit opaque, and less than enlightening (let’s be honest — sometimes we just need a dry, straightforward technical reference).

Enter these two gems. ‘The Singleton Class’ and ‘The Metaclass’, written by Patrick Farley. Genius stuff.

  • Share/Bookmark

Feb 23 2009

A Pottery Class…

A ceramics professor has two pottery classes in a semester. He takes it upon himself to run a little experiment:

In one class, the students are told that they must make one pot each week. On Monday they are given fresh materials and on Friday they hand in whatever they have created.

In the other class, the students are given the task of making a single pot; and are given the whole semester to plan, design, make and perfect it.

Come the end of semester, the professor collects and marks the final set of pots. It becomes immediately apparent that his first class has vastly outdone the second – their pots are superior in every way.

Courtesy of Andrew Russell Studios.

  • Share/Bookmark

Feb 15 2009

Poignant

6a00d83451587d69e2010537203ca8970b-800wi

  • Share/Bookmark

Feb 12 2009

Rails Voodoo: How does before_filter work?

Sometimes I am working with Rails and just take things for granted. Like before_filter and after_filter. For those who don’t use rails, basically, before_filter and after_filter are called before and after actions are processed. So instead of having to look-up my user from the database in every single action, I can create a before_filter that handles it for me, making the user available in all my actions.

Now what is cool about this is that actions have no special creation system. You just create a new class method, and *bam*, you have a new action for your controller. In that case, what sort of voodoo is going on to prepend and append the filters to our methods? Some sort of ‘alias’ trickery? But that won’t work unless the filters are evaluated after the methods, and that certainly isn’t true for our filters…

Let’s see how deep the rabbit hole goes. Looking at ActionController::Base, we find the perform_action method, which, as you can imagine, performs an action. After extracting the action name and determining whether it is a public action, it tries to ‘send’ the action. Herm, no reference to filters anywhere here.

Next, let’s look at ActionController::Filter. Here, we find a base Filter type, which is a ActiveSupport::Callbacks::Callback. Might as well take a look at that… and all we find is a typical callback object. Well, that got us nowhere. Looking back at the filters source, we can see that when the module is included, it stuffs a whole mess of methods in the base. And that is where the gold is. Look down at the InstanceMethods module. See right there, squeezed in the self.included(base), we find it. The meat and potatoes. alias_method_chain. It seems to be aliasing process and perform_action — the heart of ActionController. But what the hell is alias_method_chain? A bit of poking and prodding and googling, and we find this nice little article which explains to us that alias_method_chain :perform_action, :filters really ends up as alias_method :perform_action_with_no_filters, :perform_action and alias_method :perform_action, :perform_action_with_filters. Likewise for process. Right below, what do we find?

protected
   def process_with_filters(request, response, method = :perform_action, *arguments) #:nodoc:
      @before_filter_chain_aborted = false
      process_without_filters(request, response, method, *arguments)
   end
 
   def perform_action_with_filters
      call_filters(self.class.filter_chain, 0, 0)
   end
 
private
   def call_filters(chain, index, nesting)
      index = run_before_filters(chain, index, nesting)
      aborted = @before_filter_chain_aborted
      perform_action_without_filters unless performed? || aborted
      return index if nesting != 0 || aborted
      run_after_filters(chain, index)
   end

And there we go. A little inheritance and alias magic, and the case is closed.

  • Share/Bookmark

Feb 3 2009

Object Paradigm versus Procedural Paradigm

Why can’t we just be friends?

Clojure seems to be the buzz language of the moment, fighting for the esoteric language spotlight with Scala, Arc, Groovy, et al. Poor Erlang, it was sooooo 2008.

Clojure is a bit of a conundrum. Sitting upon the JVM, the very organs that the ‘everything is an object’ Java rests upon, Clojure is not object oriented. Except when it is, because it talks to Java libraries and what-not. While Java left a horrible taste in my mouth, I fully enjoy Ruby’s ‘everything is an object’ approach. Want to create a method that allows me to change the number 2 into a date offset from 4004 B.C.? Simply crack open that Fixnum class and add a new method. Now we can call 2.to_date and it works. Truly object oriented.

But does this always make sense? Not quite. This is the odd balance you can sometimes find in C++ libraries. This struck me while I was playing in Matlab. You see, the original purpose of an object was to encapsulate state and behavior. A dog barks. A matrix, on the other hand, does not add. Matrices are added. How are we supposed to capture this? It isn’t a behavior of the matrix itself, but it does use the state of the matrix. Matrix addition is a more … platonic concept. Nevertheless, how many times have we seen m.dot_product(m2)? So then I began to question: “Does 2 convert itself to date? Does that truly represent a behavior of 2? Or any Fixnum in general?” Not quite. So, in our Java ‘everything is an object’ world, should we have a ‘converter’ class? Does that make any sense? When was the last time you picked up your trusty ‘converter’ and used it? I’ll tell you when: never. Rather, you just did it in your head. Or on paper. Either way, it was just a calculation — there was no behavior that belonged to any object. It just … was.

Yet without objects, we can run into a brick wall. 1+1=2. [1 2]+[2 3]=[3 5]. Humans recognize which definition of + to use, but our compiler won’t. Well, unless we decide to give up dynamic typing and go fully static. Then we can. Otherwise, we get all sort of namespace collisions. Do we use the fixnum + or the matrix +? If we go static, what sort of losses do we take? Cool things like Ruby’s ActiveRecord library all of a sudden doesn’t seem to work. Poor method_missing just won’t work when we don’t know what form the arguments will arrive in.

So what can we do? C++ does it through some ‘exceptional’ cases, allowing you to define operators in the general namespace (or something like that; I don’t really know the inner specifics … I have better things to do than read the standard). So it allows us to do Matrix + Matrix instead of Matrix.add(Matrix). Nice. But what if we have a dynamic language? Well, then we might be in some trouble: we can’t tell which method to use.

Or, better, what if we have a hybrid language? Using meta-data, we can determine the type of arguments, and then map them to the appropriate function. Now if we simply tell the interpreter/compiler which method corresponds to which types of arguments, we are golden. Except for that whole ‘more work at run-time’ thing. Unfortunately, the only way to give the compiler any sort of predictive ability is to make the language static.

So now I can define a class for a dog, and implement a method ‘bark’ that truly defines the behavior of a dog. On the other hand, we can now define an (infix) + operator in the ‘platonic’ namespace that allows us to define the behavior of adding two matrices. That makes a lot more sense logically.

  • Share/Bookmark