Tuesday, 11 October 2011

Click Counter

The next example comes also from the Swing Tutorial.  Here we have a button and a label.  The button click adds one to a counter, and the label shows the number on the counter, so you can see how often you have clicked the button.

This is the code:-

(ns clojurecorner

      (javax.swing JButton JPanel JFrame JLabel SwingUtilities)
      (java.awt.event ActionListener)
      (java.awt GridLayout)))

(def click-counter (atom 0))

(defn init-gui []
  (. SwingUtilities invokeLater
    (proxy [Runnable] []
      (run []
          [frame (JFrame. "Swing application")
          button (JButton. "I'm a Swing button!")
          label (JLabel. "Number of click")]
          (.addActionListener button
             (proxy [ActionListener] []
               (actionPerformed [e]
                 (.setText label

                   (str "Clicks: " (swap! click-counter inc))))))
          (doto frame
            (.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE)
            (.setLayout (GridLayout. 0 1))
            (.add button)
            (.add label)
            (.setSize 300 200)
            (.setVisible true)))))))

(JFrame/setDefaultLookAndFeelDecorated true)

The line (def click-counter (atom 0)) creates an atom - a repository for our click counter - sets the initial value to zero, and gives it the name click-counter.

The line (swap! click-counter inc)) updates the value of the counter atom with the result of applying the function inc to the current value, and it returns the new value - a thread-friendly way to maintain the counter.

The code that handles the click event is wired up to the button via another proxy implementing an interface that supports a single method, like the code that creates the gui - in this case a proxy implementing ActionListener by providing a method actionPerformed.

Stuart Sierra on Digital Digressions has pointed out that this pattern with a single abstract method is going to be common enough to warrant a macro.  Yes I'll try that next week.  Anyway, this is how the application looks:

Monday, 3 October 2011

Hello to GUI

The next example shows the minimum possible graphical user interface application. It consists just of a window with the words “Hello World” written in it. This is based on the first example in the Java Swing Tutorial. Here is the Clojure code:

(ns clojurecorner
  (:import (javax.swing JFrame JLabel SwingUtilities)))

(defn create-and-show-gui []
  (. SwingUtilities invokeLater
    (proxy [Runnable] []
      (run []
        (JFrame/setDefaultLookAndFeelDecorated true)
        (let [frame (JFrame. "Hello World from Swing")
              label (JLabel. "Hello World")]
          (.setDefaultCloseOperation frame JFrame/EXIT_ON_CLOSE)
          (.add (.getContentPane frame) label)
          (.pack frame)
          (.setVisible frame true))))))


There are various new things happening here. Well, new to me.  First, we have imported some items from the Swing library: JFrame is the object that produces the window on the desktop, and JLabel will support the label that we will put in the frame. SwingUtilities provides essential code to run the application.

The example consists mostly of the call to the function create-and-show-gui. Now, to make this work properly we want this code to be executed in the event dispatch thread, not in our forground thread. We achieve this by passing the code to the function invokeLater in the Swing object SwingUtilities. This function requires an object that implements the interface Runnable, which essentially means it has to provide a function run(). To pass our code to the Java routines we bundle it up into a proxy: the Clojure function proxy takes, first, the class or interface to be represented (here it's Runnable), then any parameters required by a superclass (none here), and then the function or functions to be implemented – in this case the function run.

So the code in run is executed via the call to SwingUtilities.invokeLater() - this means that our main code calls this and then proceeds, allowing Swing to run the code to create the window in its own time in its own thread.

Within the function run we start by switching on the default look and feel for the GUI – that is to say the default Swing appearance. Without this the interface will get your native GUI appearance. It will still work like that, of course, it's just a matter of how you want it to look.

Next we create a frame object from the class JFrame and a label object from the class JLabel.

The next line sets the close operation to halt the program – this means that when you click the close box in the frame the application will actually close as you would expect, not just sit there.

The call to function .add inserts the label into the content area of the label, so the text will appear in the window.

The call to .pack makes the components shuffle into position and then the call to setVisible allows the window to appear on the screen.

When it appears it is in its tiniest area, but you can drag it around and open it up to read what the label says.  So it does the minimum that a GUI window needs to do.  You have to start somewhere.

Friday, 23 September 2011

Drop every nth item of a sequence

Start with a simple sequence:-

user=> (def xs [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20])
user=> xs
[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20]

The task is to write a function that will drop, say, every fourth item and return the resulting sequence.

My first thought is that we can start by partitioning the sequence up into sub-sequences each, say, 4 elements, with the built-in function partition:-

user=> (partition 4 xs)
((1 2 3 4) (5 6 7 8) (9 10 11 12) (13 14 15 16) (17 18 19 20))

Then we take only the first 3 of each of these sub-sequences, thereby
omitting each fourth item overall:-

user=> (map #(take 3 %) *1)
((1 2 3) (5 6 7) (9 10 11) (13 14 15) (17 18 19))

Then we flatten these to make the whole list without the fourth ones:-

user=> (flatten *1)
(1 2 3 5 6 7 9 10 11 13 14 15 17 18 19)

However, this does not work for the general case. The function partition returns sub-sequences only until there are enough elements left in the list to have a whole sub-sequence. So 20 elements will work if you break into sub-sequences of four elements:-

user=> (partition 4 xs)
((1 2 3 4) (5 6 7 8) (9 10 11 12) (13 14 15 16) (17 18 19 20))

But not if I split by, say, six:-

user=> (partition 6 xs)
((1 2 3 4 5 6) (7 8 9 10 11 12) (13 14 15 16 17 18))

We lose 19 and 20: but if we were dropping every sixth item we would want these in. Hmm.

OK, plan B we use a list comprehension with for.

First, we want to number the elements of the list. Here is the sequence:-

user=> (for [x xs] x)
(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20)

To pick out certain ones, we number them by putting each one into a vector pair with successive numbers - provided by the function range:-

user=> (for [x (map vector (range) xs)] x)
([0 1] [1 2] [2 3] [3 4] [4 5] [5 6] [6 7] [7 8] [8 9] [9 10] [10 11] [11 12]
[12 13] [13 14] [14 15] [15 16] [16 17] [17 18] [18 19] [19 20])

We destructure the vectors into an element x and a count n, so our output can just show the element x:-

user=> (for [[n x] (map vector (range) xs)] x)
(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20)

I've confused matters by starting with a sequence that contains numbers in the first place. Well, never mind.

If I want to omit every fourth item then I want to drop the ones where n mod 4 is zero - that is, retain the ones where mod n mod 4 > 0. No, hang on - the counter n starts from zero not one - so I want to retain the ones where (n + 1) mod 4 > 0.

So I want a filter in my list comprehension (> (mod (+ n 1) 4) 0) like so:-

user=> (for [[n x] (map vector (range) xs) :when (> (mod (+ n 1) 4) 0)] x)
(1 2 3 5 6 7 9 10 11 13 14 15 17 18 19)

Does this work for every sixth item?

user=> (for [[n x] (map vector (range) xs) :when (> (mod (+ n 1) 6) 0)] x)
(1 2 3 4 5 7 8 9 10 11 13 14 15 16 17 19 20)

Interpose into a sequence

The next task is to write a function that interposes a given value between elements of a sequence and returns the result.  For example we want the function f that does this:

(f 99 [1 2 3 4 5]))  => [1 99 2 99 3 99 4 99 5]

The built in function interpose does this already but the task is to write our own.

Well, the function repeat gives us a lazy infinite list of repeats of an element x:-

user=> (take 10 (repeat 99))
(99 99 99 99 99 99 99 99 99 99)

So we want to interleave this into our original sequence.  There is a function interleave that does this:-

user=> (interleave (repeat 99) [1 2 3 4 5])
(99 1 99 2 99 3 99 4 99 5)

But we do not want the first element, just the rest, so we say:-

user=> (defn f [x ys] (rest (interleave (repeat x) ys)))
user=> (f 99 [1 2 3 4 5])
(1 99 2 99 3 99 4 99 5)

Tuesday, 23 August 2011

Basic Destructuring

A couple of examples showing destructuring - using the argument list to break up a composite value passed to a function.  The same principle applies within a let statement so it is easy to see how it works.

The function range produces a list of values from a start to an (exclusive) end number with a specified step:

user=> (range 1 10 3)
(1 4 7)

You can omit the step and it will step by 1:

user=> (range 1 10)
(1 2 3 4 5 6 7 8 9)

You can supply just the end and it will start from 0:

user=> (range 10)
(0 1 2 3 4 5 6 7 8 9)

Call it on its own and it will start at 0 and go on as long as you take numbers out:

user=> (take 20 (range))
(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19)

So, if we pass (range) as a parameter to a let statement, we can deconstruct the first few elements of the list of numbers by using a vector of parameter identifiers like this:

user=> (let [[a b c d e f g] (range)] [c e])
[2 4]

So in the body of the (let), a=0, b=1, c=2, d=3, e=4, f=5, g=6.

And so [c e] returns [2 4]

The additional character & in the parameter deconstruction sets the following identifier to a vector of the remaining parameters that have not yet been assigned.

And the keyword :as indicates that the next identifier will take the value of the whole list.  Therefore:

user=> (let [[a b & c :as d] [1 2 3 4 5]] [a b c d])
[1 2 (3 4 5) [1 2 3 4 5]]

What happens here?  From the input values [1 2 3 4 5], a takes the first value 1, b takes the next value 2, and c takes the remaining values and is set to [3 4 5].  Then d is set to the value of the whole input list, that is [1 2 3 4 5].

Compare this with the case where we do not deconstruct the input - we could set d to be the whole of the input list like so:

user=> (let [d [1 2 3 4 5]] d)
[1 2 3 4 5]

Friday, 29 July 2011

Simple Simple Recursion

The next question asks what the following function will return:

((fn foo [x] (when (> x 0) (conj (foo (dec x)) x))) 5)

I hadn't spotted until now that an anonymous function definition can give the function a name, that is to say a name that is visible inside the definition, so you can easily write recursive lambdas.

Anyway clearly this is going to loop down from 5 to 1, building up a list as it goes - so the answer is

(1 2 3 4 5)

Wrong.  This is what happens:

user=> ((fn foo [x] (when (> x 0) (conj (foo (dec x)) x))) 5)
(5 4 3 2 1)

Ha. Maybe it would be clearer (to me at any rate) if I did this with cons instead of conj:

user=> ((fn foo [x] (when (> x 0) (cons x (foo (dec x))))) 5)
(5 4 3 2 1)

The alternative way with cons instead of conj: the x and the call to foo go round the other way. But for lists, conj and cons do the same thing - they add the new element to the start of the list:

user=> (cons 1 '(2))
(1 2)
user=> (conj '(2) 1)
(1 2)

It's with vectors that conj goes the other way:

user=> (conj [2] 1)
[2 1]

when is like if except there is no else part - when the test returns false the when clause returns nil.
You can conveniently cons onto nil to start a list as you would cons onto the empty list:

user=> (cons :a nil)
user=> (cons :a '())
user=> (cons :a ())

Even though nil and () are not the same.

OK, so in this function what happens is the recursive calls burrow their way down from 5 to zero, get a nil when they are down there, and then pop their way back out consing the numbers 1, 2, 3, 4, 5 onto the return list as they go -

(foo 5)
(cons 5 (foo 4))
(cons 5 (cons 4 (foo 3)))
(cons 5 (cons 4 (cons 3 (foo 2))))
(cons 5 (cons 4 (cons 3 (cons 2 (foo 1)))))
(cons 5 (cons 4 (cons 3 (cons 2 (cons 1 (foo 0))))))
(cons 5 (cons 4 (cons 3 (cons 2 (cons 1 nil)))))
(cons 5 (cons 4 (cons 3 (cons 2 '(1))))
(cons 5 (cons 4 (cons 3 '(2 1)))
(cons 5 (cons 4 '(3 2 1)))
(cons 5 '(4 3 2 1))
'(5 4 3 2 1)

Right.  Got it.

Interleave Two Sequences

Similarly to interleave two sequences, without of course using the interleave function.

So for example [1 2 3] [:a :b :c] => [1 :a 2 :b 3 :c]

(fn [sq1] [sq2]
  (loop [src1 sq1, src2 sq2, dest []]
    (if (and (seq src1) (seq src2))
        (rest src1)
        (rest src2)
        (conj dest (first src1) (first src2)))

Wednesday, 27 July 2011

Transforming Sequences

So with those points in mind here are two examples from 4Clojure.

To pack a sequence - that is to take all runs of one or more equal elements and put them inside their own sub-sequences. At each turn round the loop get the next element and then use take-while to gather equal ones into a sub-list and use drop-while to skip over the ones waiting to be processed, like this:

(defn pack-sequence [sq]
  (loop [src sq, dest []]
    (if (seq src)
      (let [x (first src)]
          (drop-while #(= x %) src)
          (conj dest (take-while #(= x %) src))))

So for example (pack-sequence '(1 1 2 2 2 3) => '((1 1) (2 2 2) (3))

And similarly to replicate a sequence, meaning to duplicate each element a nominated number of times: use repeat to do the duplication and concat to add the elements to the growing destination sequence:

(defn replicate-sequence [sq n]
  (loop [src sq, dest []]
    (if (seq src)
        (rest src)
        (concat dest (repeat n (first src))))

So for example (replicate-sequence '(1 2 3) 2) => '(1 1 2 2 3 3)

Doing Sequences

So I have invested in The Joy Of Clojure by Fogus & Houser. I just felt like buying a book. Well, with a few of their tips I can update my scheme for transforming sequences. One observation is that "quoting the empty list isn't idiomatic Clojure" (p.34) - so you don't have to write '() because () will do. Another observation is that the idiomatic way to test whether a sequence is empty is to use (seq s), which returns nil if (empty? s), and nil evaluates to boolean false. On p.87 they point out that you can remove that call to reverse on closing a sequence transformation by starting with a vector and using conj instead of cons. So instead of:

(defn copy-sequence-1 [sq]
  (loop [src sq, dest ()]
    (if (seq src)
        (rest src)
        (cons (first src) dest))
      (reverse dest))))

You can do this:

(defn copy-sequence-2 [sq]
  (loop [src sq, dest []]
    (if (seq src)
        (rest src)
        (conj dest (first src)))

You get a vector back but that's not a problem. In fact we read "in idiomatic Clojure code lists are used almost exclusively to represent code forms" (p.90) - for data rather than code "lists rarely offer any value over vectors".

Saturday, 23 July 2011

Removing Duplicates

OK the next task is to remove successive duplicates from a sequence.  There is a Clojure function distinct that nearly does this, but it removes all duplicates, not just successive ones:-

user=> (distinct "Mississippi")
(\M \i \s \p)

My first thought is that I can build this from other existing functions.  First, partition the sequence into pairs of elements, that is to say elements 1 and 2, then elements 2 and 3, then elements 3 and 4 etc.:

user=> (partition 2 1 "Mississippi")
((\M \i) (\i \s) (\s \s) (\s \i) (\i \s) (\s \s) (\s \i) (\i \p) (\p \p) (\p \i))

Now filter out the ones where the elements are the same - ie (first %) is not equal to (second %) - because these are the ones where there is a duplicated element:

user=> (filter #(not (= (first %) (second %))) *1)
((\M \i) (\i \s) (\s \i) (\i \s) (\s \i) (\i \p) (\p \i))

(In the Clojure REPL, *1 returns the result of the previous evaluation)

And now put the remaining pairs back into a sequence by getting the first element of each pair with a map:

user=> (map first *1)
(\M \i \s \i \s \i \p)

Nope - of course this misses the final element of the original list, which was never the first element of one of the pairs.

Incidentally we can turn this sequence back into its original string form as follows:

user=> (apply str *1)

Anyway, perhaps this will require a purpose built function.  Here is the function that eliminates successive duplicates:

(defn deduplicate [sq]
  (if (empty? sq)
  (let [x (first sq)
        xs (rest sq)]
    (cons x (deduplicate (drop-while #(= x %) xs))))))

This is a basic pattern to transfer one sequence to another via a recursive function: the part that does the work is the drop-while which removes any elements from the rest of the list that match the element being processed.

To drop this into an existing line of code you would wrap the definition in a (do....) construction and let the value you've just defined be returned as the value of the expression.

However, the rules on 4Clojure say that you can't define any new functions.  Therefore it has to be an anonymous function.  How to write an anonymous recursive function? Hmm.  Here I'm going to use the loop/recur construction, so the function is iterative rather than recursive.  It contains a GOTO rather than a CALL to do the loop.  I pass two parameters, one the source sequence that the elements are coming from and the other a destination sequence which is where they will be accumulated.  Yes anyway it looks like this:

(fn [sq]
  (loop [source sq destination '()]
    (if (empty? source)
        (reverse destination)
        (let [x (first source]
              xs (rest source)]
            (drop-while #(= x %) xs)
            (cons head destination))))))

Using a recur you build the destination list the wrong way round so I return the reverse thereof.

Monday, 18 July 2011

Home-made flatten function

OK, the recursive function that flattens:

(defn my-flatten [sq]
  (if (empty? sq)
  (let [head (first sq)
        tail (rest sq)]
       (if (sequential? head)
          (concat (my-flatten head) (my-flatten tail))
          (cons head (my-flatten tail))))))

So now we have:

user=> (my-flatten '(1 2 3 4 (5 6 ( 7 8 ) 9 10 ) (11 12) 5 6))
(1 2 3 4 5 6 7 8 9 10 11 12 5 6)

Looks about right. So, you transfer a list to another list but if the next element is a list then you flatten this to get the elements out and then concatentate on to the processed version of the rest (you don't cons because this would put the elements back in a list).

Thursday, 7 July 2011

Flatten a Sequence - hmm

As for the requirement to create code that flattens a nested sequence into a flat sequence - but without using the function flatten - I couldn't think of a way to do this without bringing in a recursive function. Therefore I cheated and looked at the source code for the function flatten. It turns out that there is a Clojure function tree-seq than negotiates trees for you, thereby doing the hard bit of climbing your tree and fetching it down
in branches. So my solution is a fraud as I looked it up:

  (complement sequential?)
  (rest (tree-seq sequential? seq %)))

Of course it also helps to find the predicate sequential?, which is the general purpose tester for the compound data structures list vector etc. Now to atone for cheating I should write the recursive function anyway.

Tuesday, 5 July 2011

Fibonacci and Factorial

The next example is the Fibonacci series.  I had a feeling this would appear sooner or later.  What, haven't we done the factorial function yet?  I've been writing software on and off for thirty odd years and, incredibly, seem to have go this far without ever needing a Fibonacci number. Or a factorial function.

Anyway the trick with the Fibonacci series - and I remember this from Halloway's book - is to generate the numbers in pairs, so each element contains enough information go make the next one - so if one element is [a b], the next one is [b (+ a b)].  Your vector pair is a two number wide window into the Finonacci sequence, which flows through your windows from right to left.  Start with [0 1] and iterate this transformation and behold:

user=>(take 20 (iterate (fn [[a b]] [b (+ a b)]) [0 1]))
([0 1] [1 1] [1 2] [2 3] [3 5] [5 8] [8 13] [13 21] [21 34] [34 55] [55 89] [89
144] [144 233] [233 377] [377 610] [610 987] [987 1597] [1597 2584] [2584 4181]
[4181 6765])

We want only the second number from each pair to solve the puzzle, so we  map second:

#(map second
  (take %
    (iterate (fn [[a b]] [b (+ a b)]) [0 1])))

Clojure helps us to keep this concise.  It you pass a vector such as [0 1] to a function with a parameter list like [x] then x is set to the value of the vector within the body of the function, and you would have to winkle out the values 0 and 1 explicitly:  however, if you change the parameter list to this [[a b]] then the vector is opened up when the function is called, and within the body of the function a will be 0 and b will be 1.  You can do the same trick with other data structures.

A Palidrome detector will obviously work by comparing an object with the reverse of the object - - but hang on, take the hint - - (reverse) returns a seq - therefore you have to compare the reverse of the object with the seq of the object, like this:

#(= (reverse %) (seq %))

To work out a Factorial looks like a gift: you reduce the list of numbers from 1 to x by multiplying them together - you get the sequence of numbers from 1 to x from the function range - so factorial % comes out as

#(reduce * (range 1 %))

Wrong.  Too confident.  In fact the function (range) does not include its upper limit - so the factorial needs to be:

#(reduce * (range 1 (inc %)))

Monday, 4 July 2011

Counting the Elements

As for counting the number of elements in a sequence without using count or writing a loop - the best I could come up with before my lunch break concluded was to use a lambda (fn [x] 1) that turns everything to one, map this onto the sequence to get a load of ones, and then use reduce and plus to add these ones together:-

#(reduce + (map (fn [n] 1) %))


Adding the elements of a list of numbers is easier than this - you can use reduce and the plus operator.  To get the odd numbers from a list of numbers you user the function filter with the predicate function odd?

The the examples seem to be out of sequence here.  Anyway, the next one is to produce the reverse of a sequence without using the functions reverse or rseq.

This took a bit more thought.  In the end I changed the original sequence to a list of pair vectors where the first element is an increasing number, like this:

Starting with this list:

user=>'(:a :b :c :d)
'(:a :b :c :d)

Use a map to insert numbers in each one:

user=>(map (fn [x y] [x y]) (iterate inc 1) *1)
([1 :a] [2 :b] [3 :c] [4 :d])

Now sort this using a function that compares those numbers we added:

user=>(sort (fn [x y] (> (first x) (first y))) *1)
([4 :d] [3 :c] [2 :b] [1 :a])

Finally extract the elements by mapping second onto the result:

user=>(map second *1)
(:d :c :b :a)

So the full solution looks like this:

#(map second
  (fn [x y] (> (first x) (first y)))
  (map (fn [x y] [x y])
  (iterate inc 1)

But surely there is a simpler way?

Friday, 1 July 2011

Lambdas in Clojure

The form (fn [...] (....)) is the equivalent of (lambda (...) (....)).  It puts the parameters in a vector [...] rather than a list (...).  This comes in handy later because it clarifies the definitions especially when you use the option to use multiple argument lists.

There is also an alternative economical form for anonymous functions - for example a lambda to add 5 to a number is just #(+ % 5): to compare a number to 5 would be #(> % 5) and so on.  These are just the right size to pop into map and filter functions.  The symbol % stands for the argument to the function.

So for example the question to find the penultimate element of a list, by reversing it and then getting the second element:

(#(second (reverse %)) '(1 2 3 4)) => 3

or using function composition this could be:-

(#((comp second reverse) %) '(1 2 3 4)) => 3

which in this instance is no simpler.

When I came to the example of returning the nth element of a sequence I caught myself starting to write a loop.  Hello?  In low-level languages we write jumps: in middle-level languages we write loops: but in high-level languages we operate on compound data structures as a whole.  The first element is given by the function first.  To get later ones we drop so many from the front of the sequence and then get the first of what's left - so to get the nth element of sq we want (first (drop n sq)).

Yes there is a function nth that does this anyway but the point is to see how that works.

Wednesday, 29 June 2011

Clojure entertainment at 4clojure

The site 4clojure.com has a graduated series of tests on Clojure.  Each test presents you with one or more Clojure statements with gaps in them. The objective of each exercise is to provide some Clojure code to fill in the gap to create a meaningful Clojure expression that evaluates to true.  When you click the Run button the web page evaluates your code and tells you whether you have got it right.

The nice effect of this site is that it takes you away from the grand scheme and makes you think about the icky details.

The first puzzle gets you to note that true is a valid Clojure word that evaluates to boolean true.

Next we have a simple piece of arithmetic illustrating the operator-first lisp type notation.

Next we have an example of a method call.  In the expression

(.toUpperCase "hello world")

the first argument .toUpperCase must of course evaluate to a function - but the dot at the beginning indicates that this is a call to a method on a Java class - but which class?  Clojure works this out from the type of the
next argument, the string "hello world".

The next tests introduce lists and vectors.

Lists you can create with a literal or a function call, as '(:a :b :c) or  (list :a :b :c).

For vectors there is the literal form and two functions, so you can say [:a :b :c] or (vector :a :b :c) or (vec '(:a :b :c)).

What surprised me at this point is that the vector and the list are equal, that is:-

(= (list :a :b :c) (vector :a :b :c)) --> true

The function conj adds one or more new elements to a collection and returns a new collection.  However, conj adds the elements "at an efficient insertion spot for the underlying data structure" (Halloway p.95)

This means that when you conj into a list the added elements go in at the beginning:-

(conj '(3 4) 2 1) => (1 2 3 4)

But for a vector the new elements go in at the end:-

(conj [1 2] 3 4) => [1 2 3 4]

When you conj an element into a set then the set decides whether to accept the new element and where to put it.

Clojure uses functions first, second and rest where in trad Lisp you would have car, cadr and cdr.

Anyway, a very nice site and it runs very smoothly and gives you the appropriate exception report when you do something invalid.

Hello World in Clojure

For the first script in Clojure naturally we want to see Hello World.  In this case the script checks to see whether there are any command line arguments: this is passed in to the script via the global identifier *command-line-args*. If not, it writes Hello World to the standard output: if there are arguments it takes the first item and uses that in its greeting.

I don't think there is an explicit entry point in a Clojure program: the interpreter just starts running the first runnable code it finds.

The namespace directive at the top reflects the path to the script: in a file helloworld.clj which is in a folder examples which is in a folder that is in the classpath passed to Clojure by the script that calls the interpreter.

So we run the script from the folder c:\Users\phancock\Documents\Clojure as follows:-

>clojure examples/helloworld.clj
Hello World
>clojure examples/helloworld.clj Polly
Hello Polly

ok.  So this is the script:-

(ns examples.helloworld)
(if (empty? *command-line-args*)
    (println "Hello World")
    (println "Hello" (first *command-line-args*)))

The hard part is just getting the choreography of paths and class paths and namespaces clear in my mind. This is the bit that the books skim over to get to the easy stuff, writing the code. "With these mechanical details mastered, everything else is comparatively easy" (Kernighan & Ritchie p.6)

Wednesday, 22 June 2011

Programming Clojure

So, I'm going to take a look at programming Clojure, with some help from the book "Programming Clojure" by Stuart Halloway, published by the Pragmatic Programmers.

To get Clojure running, I've downloaded clojure-1.2.0.zip, which is the core stuff, and clojure-contrib-1.2.0.zip, which is a library of extra modules.  There's no installation process necessary - I've just unzipped these into folders in c:\Program Files (I'm on Windows 7).

Now I've created a folder c:\Users\Phancock\Documents\Clojure, where I will be putting my own code.

So finally I need a batch file that will invoke the Clojure interpreter.  This sets up the classpath to the Clojure libraries and calls Java with the namespace clojure.main, and passes the name of the script you want to run and any parameters.  So my script looks like this:-

@echo off
set CLOJURE=c:/Program Files/clojure-1.2.0/clojure.jar
set CONTRIB=c:/Program Files/clojure-contrib-1.2.0/target/clojure-contrib-1.2.0.jar
set DEV=c:/Users/phancock/Documents/Clojure
java -cp "%CLOJURE%;%CONTRIB%;%DEV%" clojure.main %*

Tuesday, 31 May 2011

Pragmatic Thinking And Learning

I am working my way through "Pragmatic Thinking And Learning" by Andy Hunt and something keeps popping out at me.  A large proportion of the books and articles that Andy cites (in fact it's one half - 45 out of a total of 90 in the bibliography) have a title that consists of a short punchy phrase, followed by a comma, followed by a longer explanatory phrase.

For example: Getting Things Done: The Art Of Stress-Free Productivity.

At first I thought this was just a boring cliché by publishers, but as I read the book I think I see more significance in the pattern.

I have a theory that - in accordance with the principles explained in the book - the poetic or metaphorical phrase before the comma is addressed to the holistic, intuitive R-mode of your brain, and the prosaic, explanatory phrase after the comma is addressed to the logical, analytic L-mode of your brain.  Thereby allowing you to see the import of the book with both halves of your brain at the same time.

I wonder if I'm on to something?