LoLClojure – Land of Lisp In Clojure

I read Conrad Barski’s excellent book Land of Lisp a couple of years ago, and worked through all the examples using CLisp, but I thought it might be fun to go through it again, but use Clojure instead. Other people have done it already, but what’s one more, eh?

As I work through the book, I will be putting all the code on Github at https://github.com/joeygibson/lolclojure

So, the first example is for a program to guess a number you are thinking of. In Lisp, defparameter allows you to rebind values, but Clojure’s def is immutable. Using a ref gets around this, though it is a bit clunky (since refs are intended for multi-threaded access.) The code is not great, and you wouldn’t write a Clojure program like this (or a Lisp program, really); it’s just to get the discussion moving. Better code is coming.

Anyway, here’s the number-guessing program in non-idiomatic Clojure. To run it, load it into a REPL, then execute (guess-my-number). If you are so enraptured with the game that you want to play it again, execute (start-over) and then (guess-my-number).

(ns lolclojure.guess)

;; Using refs for these is overkill, but the original
;; used mutable global variables.
(def small (ref 1))
(def big (ref 100))

(defn guess-my-number
  "This is, effectively, a binary search between the two extremes."
  []
  (Math/round (Math/floor (double (/ (+ @small @big) 2)))))

(defn smaller
  "The guess was too high, so lower it."
  []
  (dosync
   (ref-set big (dec (guess-my-number)))))

(defn bigger
  "The guess was too low, so raise it."
  []
  (dosync
   (ref-set small (inc (guess-my-number)))))

(defn start-over
  "Reset everything and prepare to start over."
  []
  (dosync
   (ref-set small 1)
   (ref-set big 100)))

One thought on “LoLClojure – Land of Lisp In Clojure

  1. When I started learning Clojure (I haven’t made much progress, too much stuff the client wants), this was my methodology.

Comments are closed.