Friday, February 27, 2009

Conway's Game of Life

John Conway developed the Game of Life in 1970 as an example of cellular automata. The following Clojure code uses Swing to implement the game.




(import '(javax.swing JFrame JPanel JButton)
'(java.awt BorderLayout Dimension Color)
'(java.awt.event ActionListener))

(def cells (ref {}))

(def running (ref false))

(defn init-cells []
(dosync
(dorun
(for [x (range 32) y (range 48)]
(ref-set cells
(assoc (deref cells) [x y] (= 0 (rand-int 5))))))))

(defn determine-new-state [x y]
(let [count
(+ (if (cells [(- x 1) (- y 1)]) 1 0)
(if (cells [x (- y 1)]) 1 0)
(if (cells [(+ x 1) (- y 1)]) 1 0)
(if (cells [(- x 1) y]) 1 0)
(if (cells [(+ x 1) y]) 1 0)
(if (cells [(+ x 1) (+ y 1)]) 1 0)
(if (cells [x (+ y 1)]) 1 0)
(if (cells [(- x 1) (+ y 1)]) 1 0))]

(or (and (cells [x y]) (> count 1) (< count 4))
(and (not (cells [x y])) (= count 3)))))

(defn calc-state []
(let [new-cells (ref {})]
(dosync
(dorun
(for [x (range 32) y (range 48)]
(ref-set new-cells
(assoc (deref new-cells) [x y] (determine-new-state x y)))))

(ref-set cells (deref new-cells)))))

(defn paint-cells [graphics]
(dorun (map #(let [x (first (first %))
y (second (first %))
state (second %)]

(doto graphics
(. setColor (if state Color/RED Color/WHITE))
(. fillRect (* 10 x) (* 10 y) 10 10)))

(deref cells))))

(defn toggle-thread [panel button]
(if (deref running)

(do (dosync (ref-set running false))
(. button (setText "Start")))

(do (dosync (ref-set running true))
(. button (setText "Stop"))
(. (Thread.
#(loop []
(calc-state)
(. panel repaint)
(Thread/sleep 100)
(if (deref running) (recur))))
start))))

(defn main[]

(init-cells)

(let [f (JFrame.)
b (JButton. "Start")
panel (proxy [JPanel] [] (paint [graphics] (paint-cells graphics)))]

(doto f
(. setLayout (BorderLayout.))
(. setLocation 100 100)
(. setPreferredSize (Dimension. 320 540))
(. add b BorderLayout/SOUTH)
(. add panel BorderLayout/CENTER)
(. setDefaultCloseOperation JFrame/EXIT_ON_CLOSE)
(. pack)
(. setVisible true))

(. b addActionListener
(proxy [ActionListener] []
(actionPerformed [evt] (toggle-thread panel b))))))

(main)


ref, deref, and ref-set maintain the state of the cells and whether or not the system has started or stopped. Approximately twenty percent of the cells are initialized as alive by the statement (= 0 (rand-int 5)).

Friday, February 13, 2009

Trivial Clojure and Spring Example

This is trivial example that shows how to use Clojure with Spring.

First, define and compile Hello.java, which has a getGreeting method.

public class Hello {
public String getGreeting() {
return "Hello, Alonzo Church";
}
}

Second, write a Spring hello.xml context, which defines a hello bean based on the Hello class.

<beans default-lazy-init="true"
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="hello" class="Hello"/>
</beans>

Finally, create a clj file that uses the Spring context to get the bean and invoke its getGreeting method.

(import '(org.springframework.beans.factory.xml XmlBeanFactory)
'(org.springframework.core.io FileSystemResource))

(let [factory (XmlBeanFactory. (FileSystemResource. "hello.xml"))
hello (. factory (getBean "hello"))]
(println (. hello getGreeting)))

To run it, include clojure.jar, spring.jar, and commons-logging.jar in your classpath.