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 ref
s 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)))
