Learning Clojure/History

Learning Clojure Next page

History edit

Lisp is one of the oldest of all programming languages, invented by John McCarthy in 1958. The original language spawned many variant dialects, the most predominant of which today are Common Lisp and Scheme. Clojure (pronounced "closure") is a new dialect of Lisp created by Rich Hickey. Like Scheme, Clojure is a functional dialect, meaning that it supports and encourages programming in a "functional style".

However, Clojure differs from older lisps in several important ways. Clojure code has much more syntactic sugar. For example, instead of typing (set 1 2 3), you can write #{1 2 3}. Clojure has borrowed from Python and Haskell its heavy reliance on dumb data structures: sets, maps, list, and vectors. Most of which have their own syntactic sugar. Clojure makes heavy use of vector data structures (similar to Java arrays and represented in Clojure with `[]'), preferring them to lists where possible for both aesthetic and performance reasons. Clojure also features complete interoperability with Java libraries.

To give you a taste of the language, here's a small example program in Clojure for correcting spelling (this is a translation into Clojure of Peter Norvig's Python spelling corrector):

 (defn words [text] (re-seq #"[a-z]+" (.toLowerCase text)))
 (defn train [features]
   (reduce (fn [model f] (assoc model f (inc (get model f 1)))) {} features))
 (def *nwords* (train (words (slurp "big.txt"))))
 (defn edits1 [word]
   (let [alphabet "abcdefghijklmnopqrstuvwxyz", n (count word)]
     (distinct (concat
       (for [i (range n)] (str (subs word 0 i) (subs word (inc i))))
       (for [i (range (dec n))]
         (str (subs word 0 i) (nth word (inc i)) (nth word i) (subs word (+ 2 i))))
       (for [i (range n) c alphabet] (str (subs word 0 i) c (subs word (inc i))))
       (for [i (range (inc n)) c alphabet] (str (subs word 0 i) c (subs word i)))))))
 (defn known [words nwords] (seq (for [w words :when (nwords w)]  w)))
 (defn known-edits2 [word nwords] (seq (for [e1 (edits1 word) e2 (edits1 e1) :when (nwords e2)]  e2)))
 (defn correct [word nwords]
   (let [candidates (or (known [word] nwords) (known (edits1 word) nwords) 
                        (known-edits2 word nwords) [word])]
     (apply max-key #(get nwords % 1) candidates)))

By the end of this document, you should be able to understand this code (with some help from the API reference).