Monday, November 7, 2011

Snippets

While writing my first project in Clojure, Tic Tac Toe, I noticed that there were a few lines of code that I was using over and over again. One of these lines was,

(apply (partial conj coll) x)

This line of code simply appends the items in vector x to vector coll. So if vector coll is [1 1] and x is [2 2], the result would be [1 1 2 2]. This was especially useful to me while writing Tic Tac Toe because I used vectors to implement the board. So, my natural inclination was to abstract this line of code into a utility function. Great, now I have a utility function that combines two vectors. However, now that I am finished with the Tic Tac Toe project, I have a problem. Let's say I start a new project in Clojure and I need to use that utility function. I have to open up my Tic Tac Toe project and search for that utility function. This isn't so bad, but if I hadn't put the line into a utility function, it would probably be lost in a sea of parentheses. I believe this is a problem a lot of developers run into. You write some brilliant one-liner that is extremely useful, but it gets buried as a private function in an obscure class. If you ever need to use it again, you have to dig for a while. One has to wonder if there a better way. Here's my suggestion: a personal repository of snippets. I'll define a snippet as a small function that preferably can function on it's own (no outside dependencies). If you keep your snippets repository small, modular and organized, you can simply copy and paste the snippets whenever you need them. No more searching through private functions in obscure classes. But wait, I've left out the best part, testing!! If you abstract these small snippets into their own project, they can also have their own suit of tests. So, not only do you have a central place to store all of your genius one-liners, but they are tested as well, so now you can be confident in your copy and pasting. To put this to practice, I've created a project of Clojure snippets. I added the vector combine function above and added three tests to cover it. Great! Now I know that I have a function to combine two vectors whenever I need it. And what's better, I know exactly where to find it! Beware, I am not suggesting that you create a utility library for you or your company to reference in all your projects. A lot of the usefulness of the snippet repository is that you know exactly what is there and exactly where to find it. If you create a massive library across your entire company, no one will know what is in there and all usefulness is lost. I do not believe the snippet library is very scalable, it should probably be kept personal.

2 comments:

  1. Interesting idea about the snippet library. On the topic of included snippet, there are other, potentially simpler ways to do what you're doing:

    ; the partial is not needed
    (apply conj coll x)
    ; or even simpler
    (concat coll x)

    ReplyDelete
  2. That's a good point about not needing the partial. However, I did choose not to use concat because it does not maintain the type of coll:

    user=> (concat [1 2] [3 4])
    (1 2 3 4)

    In my case, I needed to append two vectors and have a vector returned. I could just cast the result to a vector, but that seemed like overkill.

    ReplyDelete