The Little Schemer in Clojure – Chapter 1 – Toys

This is the first Chapter of a series of posts about porting The Little Schemer to Clojure. You may wish to read the intro.

The big theme in Chapter 1 is Simplicity of Data. In The Little Schemer world there are two levels in the syntax that describes data – atoms and lists. Note that an atom in TLS refers to a a string of characters (perhaps you could consider this a list element – ie a non-list), wheras in Clojure an atom refers to a unit of a transaction.

To test for atoms – we’ll use the atom? function:

(def atom?
  (fn [a]
    (not (seq? a))))

Note that we’re not using the defn syntax in Clojure but def ... fn. This is intentional because the book uses this standard, and then makes use of it later in the book when it passes anonymous functions around.

Speaking of null – the original Scheme has a different concept of nil than what we see in Clojure today. To make Clojure act like the null tests in the book – we use the null? function:

(def null?
  (fn [a]
    (or
      (nil? a)
      (= () a))))

In TLS the thematic emphasis is also on the Simplicity of Syntax. All data structures are represented by lists, and lists of lists (ie nested listed). In Clojure we have several types of data structures – but the closest to what we’re dealing with here is the Sequence.  (Now it’s more complex than that – because in Clojure a sequence is more like an iterator interface – but we’ll start there.)

The other concept to get in Chapter 1 is that lists are treated as stacks rather than arrays. We push elements on the end and pop them off. Our primitives to do this in TLS are cons to push, car to pop and cdr to get the list remainder. In Clojure this corresponds to cons to push, first to pop and rest to get the sequence remainder. (Note that Clojure also has conj, but we’ll stick to sequences and using cons for now)

The last trick that Chapter 1 introduces are nested lists. The short summary of this is that if you push a list onto a list you get a nested list (using cons). To reverse this then you pop the nested list off the list (using car/first).

The Little Schemer in Clojure

The Little Schemer is a delightful book that has been the road to LISP for many people. Highlights include the YCombinator and the metacircular evaluator.

Positive reviews abound, with this book being the key to several ‘aha’ moments:

  • This is a book that literally blew my mind.” Anthony Lewis
  • I recently read The Little Schemer and had my mind blownJamie Strachan
  • I found Lisp to be a load of brackets till I read The Little Schemer. It blew my mind, was the best programming book I have ever read.a1212
  • “The Little LISPer blew my mind.” Sal

There is much buzz in the programmer zeitgeist about this book, and whilst the software development world has changed much since it was written – if anything it is coming closer to the ideals of this book.  In many ways, it is a timeless classic, and well worth giving a new lease of life in Clojure.

The book deliberately steers away from using library functions, and instead builds up on a minimal set of primitives, in order to be able to build a lisp interpreter for that minimal set of primitives. (In addition to teaching recursion.)

This series of posts is will communicate the big ideas of each Chapter of this book in Clojure as I work through it. I’m not aiming to cover every function or every question – just those that seem the most pertinent or the most useful to the big ideas in the chapter.

Questions

Is this really a good way to learn Clojure?

Fascinating question. I don’t believe the original book was ever intended to teach ‘The Scheme Language’ – but to teach just enough for the reader to get some big ideas in Computer science.

Is this a good way to learn Clojure? No. The book is about deliberately steering away from using library functions, and instead builds up on a minimal set of primitives, in order to be able to build a lisp interpreter for that minimal set of primitives. (In addition to teaching recursion.) You can read more about this idea here.

Where does this fit in the bigger picture?

The theme is Amazing Lisp Books living again in Clojure.

Chapters

Amazing LISP Books living again in Clojure

The LISP family of languages has a rich heritage, with some epic tomes gracing Computer Science history (and our shelves) over the years.  Clojure is the latest entrant in the LISP family, bringing concurrency advances and the richness of the JVM ecosystem to the table. For Clojure this means there is much legacy code to plunder reuse.

The Little Schemer

An old favourite for many people who studied this in College or at home – The Little Schemer is the way many people have started the road to LISP.  Described as ‘mind blowing’ by some – particular highlights include the ycombinator and the metacircular interpreter.  In Clojure you can find the following online:

Practical Common LISP

Practical Common Lisp is the modern Common LISP Pickaxe – the guys at ITA software hand this to grads to get them up to speed.   The guys at Relevance have spent some time bringing this across:


Paradigms of Artificial Intelligence Programming

PAIP is a well known book that has aged well – and still remains a delight to flip through. The author Peter Norvig has served as the head of Computational Science at NASA and is now Director of Research at Google.  The opportunities for the Clojure community here are wide open because this book has some amazing stuff. In Clojure it looks like this:


On Lisp

Paul Graham has been an outstanding advocate and essayist for LISP, and many have explored LISP because of his writings. He’s also famous for his LISP startup Viaweb and it’s subsequent sale to Yahoo, plus his distinguished work in the YCombinator VC Fund.  One of his primary arguments in the essay ‘Beating the Averages’ is that LISP helps programmers by being more expressive (more powerful) and the tool that LISP has that other languages don’t is macros. How do we learn about macros? Paul Graham wrote The Book on LISP macros. Here is what it looks like in Clojure:

Lisp In Small Pieces

Lisp In Small Pieces

Lisp In Small Pieces is a wonderful book by Christian Queinnec. Lots of people have written a LISP interpreter. The author writes eleven interpreters and two compilers.

The opportunities for this to be ported to Clojure are wide open – and work has only just begun:

 

 

Structure and Interpretation of Computer Programs – SICP

 

Updated 25 May 2013

Peter Siebel Reaction

Running Checkstyle at Full Throttle on a Legacy Codebase

 TLDR;

So in summary:

You can turn on all checks for new checkins on a horrible old legacy code base in checkstyle by using checkstyle to generate a supressions file to ignore all the old mistakes.

Get new version of Checkstyle

Download the patched version here.

See the patch in Sourceforge here.

To run simply add the the following new task in your build file to generate the suppressions file from the build.xml here:

<target name="generate.suppressions"
 ...

Then you’ll need to add the following to your existing checkstyle task.

<property key="checkstyle.suppressions.file" 
file="target/suppressions.xml"/>

The Story

I think checkstyle is fantastic, because I work in a large team of developers on a large codebase, and I want to know we’re all on the same page with our coding styles.

“But it shouldn’t matter,” you might argue. “All it does is slow you down. That’s not providing benefits or reducing risks.” Fair enough. Suppose you find the following in your codebase.

...
if (inputString == "Expected String") {
...

Should the developer responsible have known? Should the code reviewer have picked it up? Is everybody on your team on the same page that This Is Not A Good Idea?

The team discussion

“But”, they argue [and here comes the broken window argument.] “This pattern is already all over the code base. The developer was just copying and pasting.”

[At this point you might groan internally and consider changing jobs. Alternatively you can acknowledge that there is real money in maintaining legacy codebases for profitable businesses, and try and find the opportunity in the murkiness.]

“That’s not a good enough reason.” You will respond. “There has to be a way for our tools to support this scenario.”

Enter Checkstyle

So checkstyle can run some checks over your code base. It comes with lots of fancy checks and it feels like it would address this situation.

So you run it with the default set of checks. You get back several thousand errors. So you alter the checks file to just the checks you’re interested in: StringLiteralEqualityCheck. Still your codebase comes back with 50 errors.

The Legacy Push-back

“We can do this,” you hope internally. We only have to touch 50 classes. Now imagine that this system has 20 000 users a day, which collectively transact about $1B a week through your system. The tolerance the organisation has for risk and defects is pretty close to zero, and changes requiring a regression test to system components not on the project will be looked on unfavourably by your project manager and user acceptance test manager. This Is Not The Way Forward.

“Well we can just use the supressions file!” you exuberantly exclaim. For these 50 errors, it should only take An Hour Of My Time to Manually Type In This XML. Because manually typing 150 lines of XML is the reason you took that Computer Science degree – right?

A New Way Forward

“Hang on a minute,” you think. “This doesn’t feel right. What I wanted was a way of working with my team where we can agree on a way of not writing crappy code. Here am I using an hour of my time to make one measly check work. What about the other checks?”

“Surely someone has done this before?” A quick search of Google and StackOverflow says no.

“What I want is for checkstyle to generate the supressions file for me, for all checks if I want. Surely generating a supressions file is about the same complexity as generating an errors file – and it already does that.”

Cracking open the checkstyle codebase one evening, it was surprisingly easy to do just that.

The Benefits

What you want is instant feedback for your developers. As soon as they save a file and run a checkstyle task in eclipse, or check it in and get an email from the Build Server – they should get some indication of whether their new code matches up with the existing codebase.

What you want is checkstyle running at full-throttle. You want all the checks possible. You don’t want to be held back by having to change legacy code to get there. You want the new code to be in line. This helps you get there.