Category Archives: Clojure

The Little Schemer in Clojure – Chapter 3 – Cons the Magnificent

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

The first function we look at is rember.

(def rember
  (fn [ a lat]
    (cond
      (null? lat) '()
      true (cond
        (= (first lat) a) (rest lat)
        true (cons (first lat)
          (rember
            a (rest lat)))))))

(println (rember 'banana '(apple banana orange)))

The big idea here is list construction. We’re applying the second commandment of the Little Lisper – use cons to build lists [sequences].

The next function we look at is firsts.

(def firsts
  (fn [l]
    (cond
      (null? l) '()
      true (cons (first (first l))
        (firsts (rest l))))))

(println (firsts '((large burger)(fries coke)(chocolate sundae))))

Here we also meet the Third Commandment of TLS. This states when building a list, describe the typical element, and then cons it onto the natural recursion. This goes back to the discussion on lat? we were having in the previous chapter.  You have to identify the base case, and then build on it.

You can see it working here

The Little Schemer in Clojure – Chapter 2 – Do It, Do It Again

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

This chapter introduces functions – and the idea of the list of atoms and the member function.

When looking at list atoms, known as a 'lat' we are introduced to writing functions in Scheme. We write the lat? function in Clojure to test for a non-nested list of atoms.

(def lat?
  (fn [l]
    (cond
      (null? l) true
      (and (seq? l)
           (atom? (first l)))
             (lat? (rest l))
      true false)))

There are a couple of things we’ve transposed here. The key one to raise is the usage of def... fn[] rather than defn. This is a convention in the book, and glues in the readers minds that functions are by default anonymous, and we give them labels after the fact. This enables the reader to get into the feel of passing anonymous functions around later.

The other thing that is introduced here is the application of the Ten Commandments (of The Little Schemer). The big ideas of the 10 Commandments is to help you solve problems recursively. The first one states that you should always ask null?  as the first question in expressing any function. In idiomatic Clojure we would use the empty? function for this – but for the sake of being closer to the book, we will not apply it in this function, but use null?.

The question behind this is what is a non-nested list of atoms and why do we care?  One of the big themes in this book is solving problems using recursion rather than iteration. The point is that before you can solve a problem using recursion (where you’ve got a nested list) you need to learn to solve it for the base case where there is no nested list. To validate the base case – we use the lat? function.

The next function we look at is the member? function.

(def member?
  (fn [a lat]
    (cond
      (null? lat) false
      true (or
        (= (first lat) a)
        (member? a (rest lat)))) ))

Why do we have this function? It’s the first useful function in the book. We also keep building our recursion skills, and it is a key building block for later functions.

You can see it working here

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