On Ruby monkeypatching and Clojure’s protocols

I read an interesting article by Dave Fayram (kirindave) contrasting monkeypatching in Ruby with protocol extension in Clojure. The article compares two of my favorite languages, but I think it was unfortunate to present monkeypatching as the main way to “associate behavior and data in a flexible way.” In fact, Ruby has a number of safer ways to extend types and single objects. (And in Ruby even monkeypatching doesn’t have to be dangerous.)

By the way, there was a very fruitful conversation on the Clojure Google group about whether type extension really is safe or has hidden dangers. It seems you can get yourself into trouble if you extend types you don’t own with protocols you don’t own. But it seems reasonably easy to avoid doing that.

So here’s Dave’s monkeypatching example:

We can achieve the same thing with a mixed-in module.

We don’t even have to have a special class definition. We can extend a single String object with the module, just once, to get our desired behavior. No other strings will be harmed by the execution of this code.

A little bulkier and perhaps less l33t than just being able to type "madness".monkeypatched, but I like it. It’s clear what’s going on: this string is being extended with a module and then we’re calling a method on the extended object. And then the object is gone because it was never bound to a variable.

If you did bind the extended String you would have to be careful not to let the it escape the scope in which you created it, say as a return value or, worse, as an instance variable on a composing object that is used elsewhere. Because then something unexpected could indeed happen. Beware side effects!

Without types in Clojure

Is there a way to do something like object.extend in Clojure? Do I have to extend a type to get something like this? Of course not. Clojure syntax isn’t dependent on types, classes, objects… We have functions!

If you don’t explicitly need your monkeyed behavior to be polymorphic, then you can just use a function. As cool as protocols and types and other strategies are, don’t forget that it’s amazing what you can do with just functions.