1. Tekstowy 'Hello World'

(print "Hello World")

2. GUI 'Hello World'

(. javax.swing.JOptionPane (showMessageDialog nil "Hello World"))

3. Silnia

(defn factorial [n]
  (apply * (range 1 (inc n))))

4. GUI konwerter Celsiusz <-> Fahrenheit

Aplikacja okienkowa Swinga - konwersja stopni Celsiusza na Fahrenheita:
(import '(javax.swing JFrame JLabel JTextField JButton)
        '(java.awt.event ActionListener)
'(java.awt GridLayout)) (defn celsius [] (let [frame (JFrame. "Celsius Converter") temp-text (JTextField.) celsius-label (JLabel. "Celsius") convert-button (JButton. "Convert") fahrenheit-label (JLabel. "Fahrenheit")] (.addActionListener convert-button
(proxy [ActionListener] [] (actionPerformed [evt] (let [c (Double/parseDouble (.getText temp-text))] (.setText fahrenheit-label (str (+ 32 (* 1.8 c)) " Fahrenheit")))))) (doto frame (.setLayout (GridLayout. 2 2 3 3)) (.add temp-text) (.add celsius-label) (.add convert-button) (.add fahrenheit-label) (.setSize 300 80) (.setVisible true)))) (celsius)

Swing Celsius

5. Symulacja kolonii mrówek (ants.clj)

Napisana przez Richa Hickeya aby zaprezentować wsparcie dla współbieżności w Clojurze. Każda mrówka to niezależny (działający równolegle) agent. Wszystkie mrówki w bezpieczny sposób wchodzą w interakcję ze środowiskiem (planszą).

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ant sim ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;   Copyright (c) Rich Hickey. All rights reserved.
;   The use and distribution terms for this software are covered by the
;   Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
;   which can be found in the file CPL.TXT at the root of this distribution.
;   By using this software in any fashion, you are agreeing to be bound by
;   the terms of this license.
;   You must not remove this notice, or any other, from this software.

;dimensions of square world
(def dim 80)
;number of ants = nants-sqrt^2
(def nants-sqrt 7)
;number of places with food
(def food-places 35)
;range of amount of food at a place
(def food-range 100)
;scale factor for pheromone drawing
(def pher-scale 20.0)
;scale factor for food drawing
(def food-scale 30.0)
;evaporation rate
(def evap-rate 0.7)

(def animation-sleep-ms 200)
(def ant-sleep-ms 40)
(def evap-sleep-ms 1000)

(def running true)

(defstruct cell :food :pheromons) ;may also have :ant and :home

;world is a 2d vector of refs to cells
(def world
     (apply vector
            (map (fn [_]
                   (apply vector (map (fn [_] (ref (struct cell 0 0)))
                                      (range dim))))
                 (range dim))))

(defn get-cell [[x y]]
  (-> world (nth x) (nth y)))      ; (nth (nth world x) y))

(defstruct ant :direction) ;may also have :food

(defn create-ant
  "create an ant at the location, returning an ant agent on the location"
  [loc dir]
    (dosync
      (let [cell (get-cell loc)
            a (struct ant dir)]
        (alter cell assoc :ant a)   ; c.ant = a
        (agent loc))))

(def home-off (/ dim 4))
(def home-range (range home-off (+ nants-sqrt home-off)))

(defn setup
  "places initial food and ants, returns seq of ant agents"
  []
  (dosync
    (dotimes [i food-places]
      (let [cell (get-cell [(rand-int dim) (rand-int dim)])]
        (alter cell assoc :food (rand-int food-range))))
    (doall
     (for [x home-range y home-range]
       (do
         (alter (get-cell [x y])
                assoc :home true)
         (create-ant [x y] (rand-int 8)))))))

(defn bound
  "returns n wrapped into range 0-b"
  [b n]
    (let [n (rem n b)]
      (if (neg? n)
        (+ n b)
        n)))

(defn wrand
  "given a vector of slice sizes, returns the index of a slice given a
  random spin of a roulette wheel with compartments proportional to
  slices."
  [slices]
  (let [total (reduce + slices)
        r (rand total)]
    (loop [i 0 sum 0]
      (if (< r (+ (slices i) sum))
        i
        (recur (inc i) (+ (slices i) sum))))))

;dirs are 0-7, starting at north and going clockwise
;these are the deltas in order to move one step in given dir
(def dir-delta {0 [0 -1]
                1 [1 -1]
                2 [1 0]
                3 [1 1]
                4 [0 1]
                5 [-1 1]
                6 [-1 0]
                7 [-1 -1]})

(defn delta-loc
  "returns the location one step in the given dir. Note the world is a torus"
  [[x y] dir]
    (let [[dx dy] (dir-delta (bound 8 dir))]
      [(bound dim (+ x dx)) (bound dim (+ y dy))]))

;(defmacro dosync [& body]
;  `(dosync ~@body))

;ant agent functions
;an ant agent tracks the location of an ant, and controls the behavior of
;the ant at that location

(defn turn
  "turns the ant at the location by the given amount"
  [loc amt]
    (dosync
     (let [cell (get-cell loc)
           ant (:ant @cell)]
       (alter cell assoc :ant (assoc ant :direction (bound 8 (+ (:direction ant) amt))))))
    loc)

(defn move
  "moves the ant in the direction it is heading. Must be called in a
  transaction that has verified the way is clear"
  [loc]
     (let [old-cell (get-cell loc)
           ant (:ant @old-cell)
           newloc (delta-loc loc (:direction ant))
           p (get-cell newloc)]
         ;move the ant
       (alter p assoc :ant ant)
       (alter old-cell dissoc :ant)
         ;leave pheromone trail
       (when-not (:home @old-cell)
         (alter old-cell assoc :pheromons (inc (:pheromons @old-cell))))
       newloc))

(defn take-food [loc]
  "Takes one food from current location. Must be called in a
  transaction that has verified there is food available"
  (let [cell (get-cell loc)
        ant (:ant @cell)]
    (alter cell assoc
           :food (dec (:food @cell))
           :ant (assoc ant :food true))
    loc))

(defn drop-food [loc]
  "Drops food at current location. Must be called in a
  transaction that has verified the ant has food"
  (let [cell (get-cell loc)
        ant (:ant @cell)]
    (alter cell assoc
           :food (inc (:food @cell))
           :ant (dissoc ant :food))
    loc))

(defn rank-by
  "returns a map of xs to their 1-based rank when sorted by keyfn"
  [keyfn xs]
  (let [sorted (sort-by (comp float keyfn) xs)]
    (reduce (fn [ret i] (assoc ret (nth sorted i) (inc i)))
            {} (range (count sorted)))))

(defn behave
  "the main function for the ant agent"
  [loc]
  (let [p (get-cell loc)
        ant (:ant @p)
        ahead (get-cell (delta-loc loc (:direction ant)))
        ahead-left (get-cell (delta-loc loc (dec (:direction ant))))
        ahead-right (get-cell (delta-loc loc (inc (:direction ant))))
        places [ahead ahead-left ahead-right]]
    (. Thread (sleep ant-sleep-ms))
    (dosync
     (when running
       (send-off *agent* #'behave))
     (if (:food ant)
       ;going home
       (cond
        (:home @p)
          (-> loc drop-food (turn 4))
        (and (:home @ahead) (not (:ant @ahead)))
          (move loc)
        :else
          (let [ranks (merge-with +
                        (rank-by (comp #(if (:home %) 1 0) deref) places)
                        (rank-by (comp :pheromons deref) places))]
          (([move #(turn % -1) #(turn % 1)]
            (wrand [(if (:ant @ahead) 0 (ranks ahead))
                    (ranks ahead-left) (ranks ahead-right)]))
           loc)))
       ;foraging
       (cond
        (and (pos? (:food @p)) (not (:home @p)))
          (-> loc take-food (turn 4))
        (and (pos? (:food @ahead)) (not (:home @ahead)) (not (:ant @ahead)))
          (move loc)
        :else
          (let [ranks (merge-with +
                                  (rank-by (comp :food deref) places)
                                  (rank-by (comp :pheromons deref) places))]
          (([move #(turn % -1) #(turn % 1)]
            (wrand [(if (:ant @ahead) 0 (ranks ahead))
                    (ranks ahead-left) (ranks ahead-right)]))
           loc)))))))

(defn evaporate
  "causes all the pheromones to evaporate a bit"
  []
  (doall
   (for [x (range dim) y (range dim)]
     (dosync
      (let [p (get-cell [x y])]
        (alter p assoc :pheromons (* evap-rate (:pheromons @p))))))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; UI ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(import
 '(java.awt Color Graphics Dimension)
 '(java.awt.image BufferedImage)
 '(javax.swing JPanel JFrame))

;pixels per world cell
(def scale 5)

(defn fill-cell [#^Graphics g x y c]
  (doto g
    (.setColor c)
    (.fillRect (* x scale) (* y scale) scale scale)))

(defn render-ant [ant #^Graphics g x y]
  (let [black (. (new Color 0 0 0 255) (getRGB))
        gray (. (new Color 100 100 100 255) (getRGB))
        red (. (new Color 255 0 0 255) (getRGB))
        [hx hy tx ty] ({0 [2 0 2 4]
                        1 [4 0 0 4]
                        2 [4 2 0 2]
                        3 [4 4 0 0]
                        4 [2 4 2 0]
                        5 [0 4 4 0]
                        6 [0 2 4 2]
                        7 [0 0 4 4]}
                       (:direction ant))]
    (doto g
      (.setColor (if (:food ant)
                  (new Color 255 0 0 255)
                  (new Color 0 0 0 255)))
      (.drawLine (+ hx (* x scale)) (+ hy (* y scale))
                (+ tx (* x scale)) (+ ty (* y scale))))))

(defn render-place [g p x y]
  (when (pos? (:pheromons p))
    (fill-cell g x y (new Color 0 255 0
                          (int (min 255 (* 255 (/ (:pheromons p) pher-scale)))))))
  (when (pos? (:food p))
    (fill-cell g x y (new Color 255 0 0
                          (int (min 255 (* 255 (/ (:food p) food-scale)))))))
  (when (:ant p)
    (render-ant (:ant p) g x y)))

(defn render [g]
  (let [v (dosync (apply vector (for [x (range dim) y (range dim)]
                                   @(get-cell [x y]))))
        img (new BufferedImage (* scale dim) (* scale dim)
                 (. BufferedImage TYPE_INT_ARGB))
        bg (. img (getGraphics))]
    (doto bg
      (.setColor (. Color white))
      (.fillRect 0 0 (. img (getWidth)) (. img (getHeight))))
    (dorun
     (for [x (range dim) y (range dim)]
       (render-place bg (v (+ (* x dim) y)) x y)))
    (doto bg
      (.setColor (. Color blue))
      (.drawRect (* scale home-off) (* scale home-off)
                 (* scale nants-sqrt) (* scale nants-sqrt)))
    (. g (drawImage img 0 0 nil))
    (. bg (dispose))))

(def panel (doto (proxy [JPanel] []
                        (paint [g] (render g)))
             (.setPreferredSize (new Dimension
                                     (* scale dim)
                                     (* scale dim)))))

(def frame (doto (new JFrame) (.add panel) .pack .show))

(def animator (agent nil))

(defn animation [x]
  ;(.setPriority (Thread/currentThread) (Thread/MIN_PRIORITY))
  (when running
    (send-off *agent* #'animation))
  (. panel (repaint))
  (. Thread (sleep animation-sleep-ms))
  nil)

(def evaporator (agent nil))

(defn evaporation [x]
  (when running
    (send-off *agent* #'evaporation))
  (evaporate)
  (. Thread (sleep evap-sleep-ms))
  nil)

(defn start-ants []
  (def ants (setup))
  (send-off animator animation)
  (dorun (map #(send-off % behave) ants))
  (send-off evaporator evaporation))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; use ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(def ants (setup))
(send-off animator animation)
(dorun (map #(send-off % behave) ants))
(send-off evaporator evaporation))

ants.clj

Podsumowanie

Program napisany w Clojurze można zapakować do jara. Do uruchomienia wystarczy Java 5 (bez żadnych dodatkowych bibliotek).

Sam Clojure rozprowadzany jest jako plik jar o wielkości około 2MB, co pozwala go łatwo dołączyć także do istniejących programów w Javie.