Functional Thinking in Clojure: Part 1
I admit it. I’m one of the poor sods who had no idea who Neal Ford was until I watched his plan for world domination at the 2011 Clojure Conj. It’s a good presentation and discussion related to how to get your technology (even if it’s not Clojure) adopted by the circles you travel in. One of the things he mentioned in passing in that talk was his Functional Thinking Series at IBM Developer Works. That got me intrigued and then I found that he had an entire presentation that he’d delivered at Strange Loop which solidified my will to go through the series.
Then I figured: “Hey! Why not turn this into a little blog series?”. So here we are. I’ll be trying to go through the Functional Thinking Series one post at a time, converting the code examples into idiomatic Clojure, as I know it. Hopefully along the way we’ll have some nice epiphanies about programming in general and Clojure in particular.
I’m doing this for a few reasons.
Even though I’ve been developing a system for a good number of months now in Clojure using almost no state, I still don’t feel like I grasp Functional Programming the same way I grasped Object-Oriented Programming. This doesn’t surprise me, but it does drive me to want to continue to wrap my brain around this extremely useful paradigm.
While I applaud Neal’s efforts to make his series extremely accessible to great mass of developers who are still programming every day in Java, I thought it would be fun to be able to see his examples in Clojure.
I’m still exploring Clojure and so I thought it would be useful to get feedback on my implementations, since I can’t release the source of the system that I’ve been developing.
I’ll be developing my conversions in a public GitHub Repo so you’re more than welcome to follow along and/or submit patches to my awful code.
For our first trick, we’re going to take the Number Classifier example from the article and convert it to Clojure and see what we come up with.
From the article:
The requirements state that, given any positive integer greater than 1, you must classify it as either perfect, abundant, or deficient. A perfect number is a number whose factors (excluding the number itself as a factor) add up to the number. Similarly, an abundant number’s sum of factors is greater than the number, and a deficient number’s sum of factors is less.
Here’s the final implementation I came up with.
Some notes about the implementation:
First, I noticed late in the game that perfect, abundant, and deficient numbers are related to something called an aliquot sum. I failed pre-calc in high school so I’m not the best person to consult about math, but I can read specs. An aliquot sum is just the sum of the proper factors of a number. My implementation ended up being written in terms of that function, rather than Neal’s implementation which chose to focus more on how to gather factors. Neal’s focus leads to the collection of
is* functions at the bottom all repeating
sum(factors(number)) - number … number;. For me, the fundamental part of this problem was comparing the aliquot sum to the number, so that’s what my implementation ends up focusing on.
I ended up (and end up in real life) yielding many of the implementation details that Neal talks about to my run time, as he said I would. I’m not sure exactly if this is a product of thinking functionally or not. After all, Java 5 introduced
for (type var : arr) and while that abstracts away the very common idiom of looping over the entirety of a collection, I’m not convinced it helps you be functional. But maybe it does. I take the use of my functional language’s constructs a step further because I’m not as concerned with being accessible to people new to functional thinking through the use of
I also make no effort to duplicate the efficiency optimization that the original Java implementation utilizes. That’s for the next part in the series.
I make no new use of higher-order functions but I do use
partial. I like this use especially as it it shows how awesome it is for everything to be a function. The
/ operator isn’t a language level operator, but a function with a funny name. Same for
>. That makes them instantly composable and thus subject to use in functions that return functions like
comp. I’m beginning to understand the benefits of composability much more in systems that I develop.
I’d be quite interested in hearing your thoughts on my implementation, how I could make it better, and other constructs in Clojure that I could be using to make this code even cleaner.
Stay tuned for the next part of this series at some point in the near future.