Thursday, December 01, 2011

Lisp Conversion

A few months and a lot of Lisp later, I find myself convinced/converted ...

... To Clojure.

Rajesh, you were right!

As far as language snobbery coolness, it has a bunch of features I like such as:
To get an idea of what I mean, here's an anonymous function to find the odd numbers in a (lazy) sequence (which could be a list, vector, or hash map):

This idea of lazy sequences is powerful, because you can do things like get the 10,001st prime number without blowing the stack:

You can just see the number-crunchy goodness, mixed in with Lispy functional precision.

As far as practicality, there is simply too much awesome stuff.
You can easily do TDD (test driven development), which is really handy if, say, you've got a bunch of math functions that you want to be sure are correct when you port/rewrite code.

Here's a screenshot of IntelliJ with a typical Leiningen project open:

You can see the typical Leiningen project layout, with /src and /test folders and subfolders. First, we'll write a function test for a function we want which sums over all values in a given sequence:

The test is in C:\Projects\CDT\Newton\test\Newton.test\core.clj, and the :use [Newton.utilities] tells it to look in the file C:\Projects\CDT\Newton\src\Newton\utilities.clj for our function. Note the use of metadata ^{:utilities true} to mark this as a utilities test, which we'll use later for organization. Our test checks that our to-be-defined sum test sums correctly over both a list and a vector.

Now here's the contents of C:\Projects\CDT\Newton\src\Newton\utilities.clj:

Finally, Leiningen allows us to choose test selectors so that we can specify which tests we want to run via project.clj:

Now by running lein at a command prompt (to save startup time) we can pick our tests:

Note in the first case, we don't expect any tests to run (test! means fetch dependencies and then run tests) because our sole test has been marked as a :utility. In the second case, we tell it to run :utility and it does, telling us that our test passed. Success!

If our test had failed, clojure's test suite would give us good information. Here, I'm going to modify the second assertion to fail. Watch what happens:

How cool is that?

I've so far read Clojure in Action and The Joy of Clojure (both highly recommended), plus enough daily doses  to actually stop mucking about and start with the CDT code already.

So, a modern Lisp with powerful IDEs, modern libraries from the JVM, interactive REPL/TDD, great documentation, learning resources, and books -- what's not to like?