Thursday, 17 April 2014

My first bit of Clojure... Hello Pi.

In trying to learn Clojure I have been knocking up various silly little programs to try to understand the language. For a Java head there were various things that were quite a paradigm shift for me. I’m an old C hack so the move (back) to functional wasn’t so hard, but never having done Lisp I struggled with a few things at first.

Postfix notation

Put simply the operator is pushed first, and the operands afterwards. This looks weird at first (compare (2 + 3) with (+ 2 3) for instance, but actually, in clojure every “form” consists of an operator and it’s operands in brackets (str “abc” “def”), or (conj set-a set-b), or (+ 2 3) - make sense now? It does make long mathematical equations odd to look at, as you can see in the code fragment which calculates Pi below.

Looping

Clojure does have loops, but idiomatically good Clojure doesn’t really use them in the way you think it might. My little Pi generator below makes use of loop and recurs, which is quite standard, but it’s not really a for loop. In fact, in Clojure, there isn’t really a for loop - only a for-each loop, for processing sets or sequences.

Lazy Sequences

Not something I’ve used outside of database or file access in Java this is a way of creating a sequence of infinite length. You can define how a sequence is generated, but it is not actually processed until you take numbers from the sequence, with the (take) function, or in some other way force evaluation of members of the sequence. Very neat indeed!

The Syntax

It does make sense when you spend a while working with it, but I’m still a beginner, and sometimes find myself doing something like:
(printf myVar ” is a bit like ” + myOtherVar) 
Of course, I get some odd output as the + is evaluated and it’s .toString representation called. + in Clojure (like the other operators) is actually a Function, so you get an odd looking function reference - much like if you .toString an object in Java.

You do get used to the brackets, and code is broken down into much smaller fragments generally, which is no bad thing, but you do end up with a more fragmented programming style. It really is like going back to my first language in some ways - Logo! Remember that? Control a turtle to draw stuff on paper, and write simple functions which you then nest up in more complicated functions. Super fun!

My little Pi generator

I’m sure there is a ton of stuff wrong with this as I’m really just learning the language, so I welcome comment and guidance, but here it is anyway.
(defn calc-pi-method1
  ([] (calc-pi-method1 100))
  ([max-recurs] (loop [r 1 pi 3.0]
    (if (> r max-recurs)
      pi
      (do
        ;(println “r=” r ” pi=” pi)
        (def div (/ 4 (* (* r 2) (+ (* r 2.0) 1) (+ (* r 2.0) 2))))
        (if (even? r)
          (def newpi (- pi div))
          (def newpi (+ pi div)))
          (recur (inc r) newpi))))
))
; main
(println (calc-pi-method1) ” compared to a Math.PI value of: ” (Math/PI))
Note that the more max-recurs you pass in the closer to Pi you get, but due to limitations in the program somewhere you never quite get to Math.PI. But it’s only to try and learn the language but not be the definitive Pi generator. :-)

Laters.

No comments:

Post a Comment