CSci 1301: Clojure examples

Running Clojure

Clojure is a functional programming language with support for parallel computation. Clojure is installed in the lab: open terminal, type "clojure" on the command line.

Clojure sample code


(+ 1 2 3) ; just like Scheme

;; function definition 
(defn average [x y] (/ (+ x y) 2))

;; function call
(average 2 5)

;; a function that returns a function
(defn addx [x] (fn [y] (+ x y)))

;; using a map to add 5 to all elements of a list
;; recall the quote notation for lists
(map (addx 5) '(1 2 3 4 5))

;; expected value:
'(6 7 8 9 10)

;; passing a "lambda" (anonymous) function to map
;; %1 means "the first argument"; you can have %2, %3, etc.
(map #(+ %1 5) '(1 2 3 4 5))

;; vectors
[1 2 3]

;; functions are applicable to any sequence (list, vector, etc)
(map #(+ %1 2) [1 2 3]) ;; results look like a list, really are a sequence

;; lazy opertaions: execute as little as possible to get the result
(nth (range 1 50) 2)
(nth (range 1 100000000000000) 2)

;; structures are called "maps" in Clojure and have
;; a different syntax:

;; a "structure" with a name and a gpa fields
;; terminology: :name is a key, 'Sally is a value 

;; a structure created "on the fly"
(def Sally {:name 'SallySmith :gpa 3.0})
(:name Sally) ; selector
(:gpa Sally)  ; selector

;; defining a structure type (struct in Scheme)
(defstruct student :name :gpa)
(struct-map student :name 'BobBrown :gpa 2.9)

nil ;; a value that represents an empty list; also means "false" in cond

;; strings are Java string; you can call Java methods on them
;; in Java you would write mystring.split(), mystring.toUpperCase
(map (fn [x] (.toUpperCase x)) (.split "Dasher Dancer Prancer" " "))

;; functions of varying number of arguments
(def min12 (fn ([x] x) 
               ([x y] (if (< x y) x y))
))
(min12 4)
(min12 2 3)

;; Examples from
;; http://en.wikibooks.org/wiki/Clojure_Programming/By_Example

;; there is a special construct for tail recursion: recur
(defn factorial [n]
  (defn fac [n acc]
    (if (zero? n)
       acc
      (recur (- n 1) (* acc n)))) ; recursive call to fac, 
      ; but reuses the stack; n will be (- n 1), and acc will be (* acc n)
  (fac n 1))

;; loops are written using recur
(loop [cnt 5 acc 1]
  (if (zero? cnt)
    acc
    (recur (dec cnt) (* acc cnt))))

;;;; Concurrency (parallel programming)
;; Clojure uses Java threads. It provides different types of shared
;; mutable data and operations for modifying these data in a safe way 

;; The three types are: refs (references), agents, and atoms

;; Refs are shared among threads and are modified in a transaction.
;; A transaction is an all-or-nothing sequence of steps: either all
;; steps are done with the exclusive ownership of the data, or none 
;; are done, and the transaction will retry later.
;; More here:
;; http://clojure.org/refs

;; define a reference r with a value 6
(def r (ref 6))

;; an update must be done in a transaction "dosync"
(dosync (ref-set r 5))

;; get the value in r
@r

;; Agents: asynchronous safe modification
;; Unlike refs, where the thread will wait for dosync to finish,
;; an agent sends a request for a modification, and the program 
;; continues. 
;; Functions that modify an agent are queued and execute one at a 
;; time when the agent becomes available.

;; define an agent "a" with a value 1
(def a (agent 1))

;; "send" an increment request to a (add 1 to a)
(send a inc)

;; wait for all requests to a (at the time of await) to finish
(await a)

;; get the value in a
@a

;; Atoms are modified in a synchronous manner, i.e. a thread with a 
;; request to change an atom will wait for the function to return.
;; A request for change is applied without "locking" the atom. 
;; If another thread has changed the atom after the modifying function 
;; started and before it returned then the function is retried. 
;; Therefore functions applied to atoms cannot have side affects
;; on anything other than the atom itself

;; define an atom atm with a value 1
(def atm (atom 1))

;; swap! is sending an increment request to atm
(swap! atm inc)

;; get the value of the atom
@atm

CSci 1301 course web site.

The views and opinions expressed in this page are strictly those of the page author. The contents of this page have not been reviewed or approved by the University of Minnesota.