Introduction to Clojure
Clojure is a modern, functional programming language that runs on the Java Virtual Machine (JVM). It combines the interactive development of a scripting language with an efficient and robust infrastructure for multithreaded programming.
Why Clojure?
- Functional Programming: Clojure is a functional-first language with immutable data structures
 - Lisp Dialect: Simple, consistent syntax with powerful macro system
 - JVM Integration: Full access to Java libraries and ecosystem
 - Concurrency: Built-in support for safe, easy concurrent programming
 - Dynamic: Interactive development with REPL-driven workflow
 
Installing Clojure
There are several ways to install Clojure:
1. Using Leiningen (Recommended)
# On macOS with Homebrew
brew install leiningen
# On Linux (Debian/Ubuntu)
sudo apt-get install leiningen
# On Windows (using Chocolatey)
choco install leiningen
                
                
                2. Using Clojure CLI tools
# On macOS with Homebrew
brew install clojure/tools/clojure
# On Linux (using install script)
curl -O https://download.clojure.org/install/linux-install-1.10.3.1029.sh
chmod +x linux-install-1.10.3.1029.sh
sudo ./linux-install-1.10.3.1029.sh
                
                
                Running Clojure
Start a REPL (Read-Eval-Print Loop) to interact with Clojure:
With Leiningen
lein repl
                
                
                With Clojure CLI
clj
                
                
                Basic Syntax
Clojure is a Lisp dialect, so everything is expressed in parentheses:
; This is a comment
; Simple expressions
(+ 1 2 3)       ; => 6
(* 2 3)         ; => 6
(/ 10 2)        ; => 5
; Function calls look the same
(str "Hello" " " "World") ; => "Hello World"
                
                
                Data Types
Clojure has several built-in data types:
; Numbers
42              ; Integer
3.14            ; Double
1/3             ; Ratio
; Strings
"Hello World"
; Characters
\a \b \c
; Booleans
true false
; Keywords (like Ruby symbols or Java enums)
:name :age :price
; Nil (null/none value)
nil
                
                
                Defining Variables
Use def to create global bindings:
(def x 10)
(def name "Alice")
(def pi 3.14159)
(println x)     ; => 10
(println name)  ; => "Alice"
                
                
                Defining Functions
Create functions with defn:
; Simple function
(defn greet [name]
  (str "Hello, " name "!"))
(greet "Alice") ; => "Hello, Alice!"
; Multi-arity function
(defn greet
  ([] (greet "World"))
  ([name] (str "Hello, " name "!")))
(greet)         ; => "Hello, World!"
(greet "Bob")   ; => "Hello, Bob!"
; Function with docstring
(defn square
  "Returns the square of x"
  [x]
  (* x x))
(square 5)      ; => 25
                
                
                Data Structures
Clojure has several immutable, persistent data structures:
Lists
'(1 2 3 4)      ; List literal
(list 1 2 3 4)  ; Same as above
; Lists are evaluated as function calls
(+ 1 2 3)       ; => 6
                
                
                Vectors
[1 2 3 4]       ; Vector literal
(vector 1 2 3 4); Same as above
; Access by index
(def v [10 20 30 40])
(get v 1)       ; => 20
(v 1)           ; => 20 (same as above)
                
                
                Maps
{:name "Alice" :age 30}   ; Map literal
(hash-map :name "Alice" :age 30) ; Same as above
; Access values
(def person {:name "Bob" :age 25})
(get person :name)       ; => "Bob"
(person :name)           ; => "Bob" (same as above)
(:name person)           ; => "Bob" (keyword as function)
                
                
                Sets
#{1 2 3}        ; Set literal
(hash-set 1 2 3); Same as above
; Check membership
(def numbers #{1 2 3 4})
(contains? numbers 2)    ; => true
(contains? numbers 5)    ; => false
                
                
                Control Flow
Clojure provides several control flow constructs:
if
(if (> 3 2)
  "3 is greater than 2"
  "3 is not greater than 2")
; => "3 is greater than 2"
                
                
                when
(when (> 3 2)
  (println "It's true!")
  "This is returned")
; Prints "It's true!" and returns "This is returned"
                
                
                cond
(defn grade [score]
  (cond
    (>= score 90) "A"
    (>= score 80) "B"
    (>= score 70) "C"
    (>= score 60) "D"
    :else "F"))
(grade 85)      ; => "B"
                
                
                case
(defn day-name [n]
  (case n
    1 "Monday"
    2 "Tuesday"
    3 "Wednesday"
    4 "Thursday"
    5 "Friday"
    6 "Saturday"
    7 "Sunday"
    "Invalid day"))
(day-name 3)    ; => "Wednesday"
                
                
                Looping and Recursion
Clojure provides several ways to loop:
loop/recur
(loop [i 0]
  (when (< i 5)
    (println i)
    (recur (inc i))))
; Prints 0 through 4
                
                
                doseq
(doseq [n (range 5)]
  (println n))
; Prints 0 through 4
                
                
                dotimes
(dotimes [i 5]
  (println i))
; Prints 0 through 4
                
                
                Recursive function
(defn factorial [n]
  (if (<= n 1)
    1
    (* n (factorial (dec n)))))
(factorial 5)   ; => 120
                
                
                Working with Java
Clojure has excellent Java interoperability:
; Create Java objects
(def date (java.util.Date.))
; Call methods
(.getTime date) ; => milliseconds since epoch
; Static methods
(System/currentTimeMillis)
; Import classes
(import 'java.util.ArrayList)
; Use Java collections
(def alist (ArrayList. [1 2 3]))
(.add alist 4)
alist           ; => [1 2 3 4]
                
                
                Next Steps
Now that you've learned the basics, you can explore:
- Clojure Data Structures - More about collections
 - Functions - Higher-order functions and functional patterns
 - Sequences - Working with lazy sequences