gypsydave5

The blog of David Wickes, software developer

Three Ways with Clojure

I’ve been working with Clojure in the last few days, both looking at the Clojure Koans and another resource I’ve discovered 4clojure.com. I’d like to share a nice problem I saw there, and some of the solutions to it which I think expose some of the things I’m beginning to appreciate about the language.

The Problem

as stated on 4clojure.

Write a function which returns the Nth element from a sequence. (Without using nth)

nth is the obvious answer to the problem, as it returns the nth element in a sequence:

(= 2 (nth 1 '(1 2 3 4)))

We need to get to a function that will do the same, something that will fit in the blank space below:

(= (___ '(4 5 6 7) 2) 6)

Solution 1: recurring

(fn my_nth [seqn n] (if
    (zero? n)
    (first seqn)
    (my-nth (rest seqn) (dec n))))

Here we use recurrance, setting the breaking point as the iteration where n is zero using if, at which point the function returns the first value of the sequence. If it’s not, we fire the function again, but this time chopping off the first member of the sequence ((rest seqn) returns the rest) and decrementing the value of n by one. We walk through the sequence, losing items from the front of the sequence n times, until we get to the index.

We’ve named the function my_nth, but we could easily anonymize it:

(fn [seqn n] (if
    (zero? n)
    (first seqn)
    (recur (rest seqn) (dec n))))

recur is neat - it executes the expressions that follow it, then rebinds the values hey produce to the bindings of the recursion point, in this case the fn method. We then get moved back to that method with the new values, causing the recusion. Very cool.

Usually recursion is a neat way of writing a short function; here it’s pretty longwinded. We can get smaller…

Solution 2: taking

(fn [seqn n] (last (take (inc n) seqn)))

Here we take the first one-more-than-n (inc increments its argument) items from the sequence, and then take the last one from the end of that new list- which will be the nth element.

take is used in many of the examples I’ve seen as a way of accessing a sequence which may be infinite like the Fibonacci series - see some of the examples over at Wikibooks.

We can squeeze more succinctness in there using some alternative syntax:

#(last (take (inc %2) %1))

But if you want to be really succinct:

###Solution 3: ripping off Java

.get

Clojure gives you access to Java methods and fields through the use of the dot (.) operator, which takes the form (.instanceMember instance arguments*). Here we’re using the get() method from the Java Lists interface, which we get to use on these instances as they are, well, Java lists. which takes one argument - and luckily for us its the index! We’re calling get(6) on the list, which gives us the answer we want.

This is pretty close to cheating, but it goes to show how Clojure’s access to Java gives us a whole other language of libraries and methods to play with.