Clojure Clash Course
====================
Syntax
——
Like Lisp and Scheme, syntax is in prefix notation with parentheses to specify
beginnings and ends.
(what-to-do operand1 operand2 …)
(what-to-do) if no operand at all
var if you want the value of a variable; no parentheses
literal e.g., 5, “hello”, true
Examples (Haskell-like on the left, Clojure on the right):
x>0 (> x 0)
2-x*3 (- 2 (* x 3))
if x>0 (if (> x 0)
then 2-x*3 (- 2 (* x 3))
else 4*y (* 4 y))
\x y -> if x>0 (fn [x y] (if (> x 0)
then 2-x*3 (- 2 (* x 3))
else 4*x (* 4 y)))
#(if (> %1 0)
(- 2 (* %1 3))
(* 4 %2))
f x y = if x>0 (defn f [x y]
then 2-x*3 (if (> x 0)
else 4*x (- 2 (* x 3))
(* 4 x)))
four = 2+2 (def four (+ 2 2))
f 5 6 (f 5 6)
Note: Can’t have (f 5).
let x=5 (let [x 5 y 1]
y=6 (+ x x y))
in x+x+y Note: On the upside, varargs supported!
[1, 2, 3] ‘(1 2 3)
Note: (1 2 3) would mean that 1 is what to do.
1 : 2 : 3 : [] (cons 1 (cons 2 (cons 3 () )))
Homoiconic
———-
Notice how list syntax is almost the same as code syntax. In fact there is an
“eval” function to take a list and run it as code, e.g.:
‘(+ 3 5) is a list, but then you can do
(eval ‘(+ 3 5))
-> (+ 3 5)
-> 8
“Homoiconic” refers to having the same format for both code and data (lists
here). You can now build a list (that will become code later), store it
somewhere, then later retrieve it and run it.
Semantics
———
Also like Lisp and Scheme.
Typing: Dynamic typing.
(if (> 1 0) “hello” 4)
is legal.
‘(1 “hello” true)
is legal.
Evaluation: Like most languages, not lazy.
(f (g 1 2) (h 3 4))
(g 1 2) and (h 3 4) evaluated until values known before calling f. (If f is a
function, not “if”, “let”, etc.)
However, a lazy list type called “sequence” is provided.
There is also a macro system for defining your own constructs.
Thread-safe mutable variables
—————————–
Most standard library types and data structures are immutable.
However, thread-safe mutable cells are available. Imagine a mutable pointer
that you can change what it points to; but still point it to immutable data.