To the Conj, in flight monkey patching

It was a long flight for me to the Conj, so I had some time to throw at my patchin library... adding support for sets, sequences, and cross compilation to ClojureScript. One little hack that occurred to me was to monkey patch clojure.data/diff-sequence, as the diff produced by Clojure on sequences is not convenient for patch application, or as a transmission format. Monkey patching solved my immediate problem pretty handily.

My colleague Mark tells me that Ruby people love monkey patching, and has been pointing out situations where it can be used for fun and profit. One simple example is when another colleague, Eli, was having trouble with a fixture. Sadly fixtures don't have a way to know which function they are actually running, because they are passed an anonymous function by clojure.test. A prime candidate for monkey patching!

(use-fixtures :each
  (fn [f]
    (with-redefs [test-var identity]
      (println "The test is:" (f)))))

To understand how this works you need to take a peek at the clojure.test code and notice that test-var is a function that executes the test. By redefing it we are able to just return the test instead.

If there is something you can't possibly do because the language or library implementer didn't provide a hook for it, you can probably do it with a redef. Fortunately the Clojure core code and most libraries are quite concise and easy to read, so finding a hook is usually pretty easy.

Obviously monkey patching is not something to do proudly or flagrantly, but it is a handy tool to have in the bag when you get stuck due to limitations in code outside of your control.

I'm super excited to be here, hope to talk with you tomorrow if you are attending!

No comments:

Post a Comment