-
Clojure is homophonic language, it means the program structure is similar to its syntax
-
Every statement evaluate to one value ex (+ 1 2) => 3
-
( ) is a list
-
Lists are call, first element is operator the rest is arguments
-
No call expression use infix or postfix position
-
Clojure Scalar Literals: String, Boolean, NIL, Char, Keyword, Symbol, Number, Regex
-
Keyword always prefixed with colon (:), keyword also can contain namespace :namespace/name
-
Symbol evaluate to value in runtime, value include those held by vars (like global registry), Java class, local ref, etc
-
Symbol must begin with non numeric
-
Collection Literals
-
List -> (1 2 3), Vector -> [ 1 2 3 ], Map -> {:key “value”}, Set -> #{ 1 2 3 }
-
Evaluation can be suppressed with ‘
-
Vars can be referred to by prefixing a symbol with #’
14.Dereference (yielding value) from reference with @
user=> (def nama "Gilang")
#'user/nama
user=> 'nama
nama
user=> #'nama
#'user/nama
user=> @#'nama
"Gilang"
user=> nama
"Gilang"
-
Symbol evaluation are tied up with namespaces
-
Namespace is Clojure's funamental unit of code modularity
-
Vars are defined by def
(def x 1)
, equivalent tovar x = 1
in javascript -
Dont use var to hold mutable value
-
Symbol in function can evaluate 2 things: the value of named var, clojure special form
-
Clojure Special Form
-
Quote '
Surpress evaluation of clojure expression. List are usually evaluated as calls, quoting a list suppressed that evaluation, yielding list it self
-
do
Evaluates all expressions, yields the last value. example
(do (println "hi") (apply * [4 5 6])) ;= hi ;= 120
-
Defining Vars: def
(def x 1)
-
Local Bindings: let
Allow to define named references that lexically scoped to the extend of the let expression (let defines local). Let are imutable, you can't change the value later.
(defn hypot [x y] (let [x2 (* x x) y2 (* y y)] (Math/sqrt (+ x2 y2))))
- Destructuring
Clojure destructuring provides a concise syntax for declaratively pulling apart collections and binding values contained therein as named locals within a let form. And, because destructuring is a facility provided by let, it can be used in any expression that implicitly uses let (like fn, defn, loop, and so on).
Sequential destructuring: clojure list, vector, seqs, Any class implementing java.util.List, java arrays, String
Example
(def v [42 "foo" 99.2 [5 12]])
;= #'user/v
(let [[x y z] v]
(+ x z))
;= 141.2
Retaining original value
(let [[x _ z :as original-vector] v]
(conj original-vector (+ x z)))
;= [42 "foo" 99.2 [5 12] 141.2]
Map destructuring: clojure hash-map, array-map, record, any cmass implement java.util.Map, a value that has get method, vector, string, array
Example
(def m {:a 5 :b 6
:c [7 8 9]
:d {:e 10 :f 11}
"foo" 88
42 false})
;= #'user/m
(let [{a :a b :b} m]
(+ a b))
;= 11
Having let key same as map key
(def chas {:name "Chas" :age 31 :location "Massachusetts"})
;= #'user/chas
(let [{:keys [name age location]} chas]
(format "%s is %s years old and lives in %s." name age location))
;= "Chas is 31 years old and lives in Massachusetts."
More complex example
(let [{[x _ y] :c} m]
(+ x y))
;= 16
(def map-in-vector ["James" {:birthday (java.util.Date. 73 1 6)}])
;= #'user/map-in-vector
(let [[name {bd :birthday}] map-in-vector]
(str name " was born on " bd))
;= "James was born on Thu Feb 06 00:00:00 EST 1973"