Basic Syntax
1;; Comments start with semicolon
2
3;; Variables (immutable by default)
4(def x 42)
5(def pi 3.14159)
6
7;; Functions
8(defn square [x]
9 (* x x))
10
11(defn greet [name]
12 (str "Hello, " name "!"))
13
14;; Multi-arity functions
15(defn greet
16 ([] (greet "World"))
17 ([name] (str "Hello, " name "!")))
18
19;; Anonymous functions
20(fn [x] (* x x))
21#(* % %) ; Shorthand
22((fn [x] (* x x)) 5) ; => 25
23
24;; Let bindings
25(let [x 10
26 y 20]
27 (+ x y)) ; => 30
Data Structures (Immutable)
Lists
1;; Create lists
2'(1 2 3 4)
3(list 1 2 3 4)
4
5;; Access
6(first '(1 2 3)) ; => 1
7(rest '(1 2 3)) ; => (2 3)
8(nth '(1 2 3) 1) ; => 2
9
10;; Operations
11(cons 0 '(1 2 3)) ; => (0 1 2 3)
12(conj '(1 2 3) 0) ; => (0 1 2 3) (adds to front)
Vectors
1;; Create vectors
2[1 2 3 4]
3(vector 1 2 3 4)
4
5;; Access
6(get [1 2 3] 1) ; => 2
7([1 2 3] 1) ; => 2 (vector as function)
8(nth [1 2 3] 1) ; => 2
9
10;; Operations
11(conj [1 2 3] 4) ; => [1 2 3 4] (adds to end)
12(assoc [1 2 3] 1 99) ; => [1 99 3]
13(subvec [1 2 3 4 5] 1 4) ; => [2 3 4]
Maps
1;; Create maps
2{:name "John" :age 30}
3(hash-map :name "John" :age 30)
4
5;; Access
6(get {:name "John"} :name) ; => "John"
7(:name {:name "John"}) ; => "John" (keyword as function)
8({:name "John"} :name) ; => "John" (map as function)
9
10;; Operations
11(assoc {:name "John"} :age 30) ; => {:name "John" :age 30}
12(dissoc {:name "John" :age 30} :age) ; => {:name "John"}
13(merge {:a 1} {:b 2}) ; => {:a 1 :b 2}
14(update {:count 5} :count inc) ; => {:count 6}
Sets
1;; Create sets
2#{1 2 3 4}
3(hash-set 1 2 3 4)
4
5;; Operations
6(conj #{1 2 3} 4) ; => #{1 2 3 4}
7(disj #{1 2 3 4} 2) ; => #{1 3 4}
8(contains? #{1 2 3} 2) ; => true
9
10;; Set operations
11(clojure.set/union #{1 2} #{2 3}) ; => #{1 2 3}
12(clojure.set/intersection #{1 2 3} #{2 3 4}) ; => #{2 3}
13(clojure.set/difference #{1 2 3} #{2 3 4}) ; => #{1}
Control Flow
Conditionals
1;; if
2(if (> x 10)
3 "Greater"
4 "Not greater")
5
6;; when (no else clause)
7(when (> x 10)
8 (println "Greater")
9 (do-something))
10
11;; cond
12(cond
13 (< x 0) "Negative"
14 (= x 0) "Zero"
15 (> x 0) "Positive"
16 :else "Unknown")
17
18;; case
19(case day
20 :monday "Start of week"
21 :friday "End of week"
22 (:saturday :sunday) "Weekend"
23 "Midweek")
24
25;; if-let (bind and test)
26(if-let [result (find-something)]
27 (println "Found:" result)
28 (println "Not found"))
29
30;; when-let
31(when-let [result (find-something)]
32 (println "Found:" result)
33 (process result))
Sequences and Collections
Sequence Operations
1;; map
2(map inc [1 2 3 4]) ; => (2 3 4 5)
3(map + [1 2 3] [10 20 30]) ; => (11 22 33)
4
5;; filter
6(filter even? [1 2 3 4 5 6]) ; => (2 4 6)
7(remove odd? [1 2 3 4 5 6]) ; => (2 4 6)
8
9;; reduce
10(reduce + [1 2 3 4 5]) ; => 15
11(reduce + 100 [1 2 3]) ; => 106 (with initial value)
12
13;; take/drop
14(take 3 [1 2 3 4 5]) ; => (1 2 3)
15(drop 2 [1 2 3 4 5]) ; => (3 4 5)
16
17;; partition
18(partition 2 [1 2 3 4 5 6]) ; => ((1 2) (3 4) (5 6))
19(partition-all 2 [1 2 3 4 5]) ; => ((1 2) (3 4) (5))
20
21;; group-by
22(group-by even? [1 2 3 4 5 6]) ; => {false [1 3 5], true [2 4 6]}
23
24;; sort
25(sort [3 1 4 1 5 9]) ; => (1 1 3 4 5 9)
26(sort-by :age [{:name "John" :age 30} {:name "Jane" :age 25}])
Lazy Sequences
1;; range
2(range 10) ; => (0 1 2 3 4 5 6 7 8 9)
3(range 5 10) ; => (5 6 7 8 9)
4
5;; repeat
6(take 5 (repeat "x")) ; => ("x" "x" "x" "x" "x")
7
8;; cycle
9(take 5 (cycle [1 2 3])) ; => (1 2 3 1 2)
10
11;; iterate
12(take 5 (iterate inc 0)) ; => (0 1 2 3 4)
13
14;; lazy-seq (custom lazy sequence)
15(defn fibonacci
16 ([] (fibonacci 0 1))
17 ([a b] (lazy-seq (cons a (fibonacci b (+ a b))))))
18
19(take 10 (fibonacci)) ; => (0 1 1 2 3 5 8 13 21 34)
Destructuring
1;; Vector destructuring
2(let [[a b c] [1 2 3]]
3 (+ a b c)) ; => 6
4
5;; With rest
6(let [[first & rest] [1 2 3 4 5]]
7 [first rest]) ; => [1 (2 3 4 5)]
8
9;; Map destructuring
10(let [{:keys [name age]} {:name "John" :age 30}]
11 (str name " is " age)) ; => "John is 30"
12
13;; With defaults
14(let [{:keys [name age] :or {age 0}} {:name "John"}]
15 age) ; => 0
16
17;; Function parameters
18(defn greet [{:keys [name age]}]
19 (str name " is " age " years old"))
20
21(greet {:name "John" :age 30})
Macros
1;; Simple macro
2(defmacro unless [test & body]
3 `(if (not ~test)
4 (do ~@body)))
5
6(unless false
7 (println "This will print"))
8
9;; Macro with gensym
10(defmacro with-logging [expr]
11 `(let [result# ~expr]
12 (println "Result:" result#)
13 result#))
14
15;; Threading macros
16(-> 5
17 (+ 3)
18 (* 2)
19 (- 1)) ; => 15 (same as (- (* (+ 5 3) 2) 1))
20
21(->> [1 2 3 4 5]
22 (map inc)
23 (filter even?)
24 (reduce +)) ; => 12
Namespaces
1;; Define namespace
2(ns myapp.core
3 (:require [clojure.string :as str]
4 [clojure.set :as set]))
5
6;; Use functions
7(str/upper-case "hello") ; => "HELLO"
8(set/union #{1 2} #{2 3}) ; => #{1 2 3}
9
10;; Refer specific functions
11(ns myapp.core
12 (:require [clojure.string :refer [upper-case lower-case]]))
13
14(upper-case "hello") ; => "HELLO"
State Management
Atoms (Synchronous, Independent)
1;; Create atom
2(def counter (atom 0))
3
4;; Read
5@counter ; => 0
6
7;; Update
8(swap! counter inc) ; => 1
9(swap! counter + 10) ; => 11
10
11;; Set
12(reset! counter 0) ; => 0
Refs (Synchronous, Coordinated)
1;; Create refs
2(def account1 (ref 1000))
3(def account2 (ref 500))
4
5;; Transaction
6(dosync
7 (alter account1 - 100)
8 (alter account2 + 100))
9
10@account1 ; => 900
11@account2 ; => 600
Agents (Asynchronous)
1;; Create agent
2(def logger (agent []))
3
4;; Send action
5(send logger conj "Log entry 1")
6(send logger conj "Log entry 2")
7
8;; Wait for completion
9(await logger)
10
11@logger ; => ["Log entry 1" "Log entry 2"]
Java Interop
1;; Call static method
2(Math/pow 2 3) ; => 8.0
3
4;; Create object
5(def date (java.util.Date.))
6
7;; Call method
8(.getTime date)
9
10;; Access field
11(.-field object)
12
13;; Import
14(import '(java.util Date Calendar))
15(import '[java.io File FileReader])
16
17;; Chaining
18(.. "hello"
19 (toUpperCase)
20 (substring 0 3)) ; => "HEL"
Practical Examples
File I/O
1;; Read file
2(slurp "file.txt")
3
4;; Write file
5(spit "output.txt" "Hello, World!")
6
7;; Read lines
8(with-open [rdr (clojure.java.io/reader "file.txt")]
9 (doall (line-seq rdr)))
HTTP Request
1;; Using clj-http library
2(require '[clj-http.client :as http])
3
4;; GET request
5(http/get "https://api.example.com/data")
6
7;; POST request
8(http/post "https://api.example.com/data"
9 {:body (json/write-str {:key "value"})
10 :headers {"Content-Type" "application/json"}})
JSON Processing
1;; Using cheshire library
2(require '[cheshire.core :as json])
3
4;; Parse JSON
5(json/parse-string "{\"name\":\"John\",\"age\":30}" true)
6; => {:name "John" :age 30}
7
8;; Generate JSON
9(json/generate-string {:name "John" :age 30})
10; => "{\"name\":\"John\",\"age\":30}"
Testing
1(ns myapp.core-test
2 (:require [clojure.test :refer :all]
3 [myapp.core :refer :all]))
4
5(deftest test-square
6 (testing "Square function"
7 (is (= 4 (square 2)))
8 (is (= 9 (square 3)))))
9
10(deftest test-greet
11 (testing "Greet function"
12 (is (= "Hello, John!" (greet "John")))))
Further Reading
Related Snippets