## 2. Clojure Syntax If the syntax is good enough for the information, it should be good enough for the meta-information.
— Erik Naggum
JavaClojure
`int i = 5;`
`(def i 5)`
```if (x == 1)
return y;
else
return z;```
```(if (= x 1)
y
z)```
`x * y * z;`
`(* x y z)`
`foo(x, y, z);`
`(foo x y z)`
`foo.bar(x);`
`(.bar foo x)`

## Lists

Evaluated as function calls

``````    (inc 1)
;=> 2``````

## Invoking functions

``````(+ 1 2)
;=> 3``````

Always in prefix form

## Empty list

``````()
;=> ()``````

## Making lists

``````(cons 1 ())
;=> (1)``````
``````(cons 1 (cons 2 ()))
;=> (1 2)``````
``````(list 1 2 3)
;=> (1 2 3)``````

## Vectors

`[1 2 3 4]`

Preferred over lists; easier to write

Order 1 count and lookup by index

``````(get [10 20 30 40 50] 3)
;=> 40``````

Similar to arrays, but can be added to

## Vector operations

``````(conj [1 2 3] 4)
;=> [1 2 3 4]``````
``````(pop [1 2 3 4])
;=> [1 2 3]``````
``````(assoc [1 2 3 4] 0 5)
;=> [5 2 3 4]``````
``````(vec (list 1 2 3 4))
;=> [1 2 3 4]``````
``````(cons 0 [1 2 3 4])
;=> (0 1 2 3 4)``````

## Equality by value

``````(def a [1 2 3 4])
(= a a)
;=> true``````
``````(def b [1 2 3 4])
(= a b)
;=> true``````
 `a` and `b` are different objects
``````(identical? a b)
;=> false``````

## Sequential equality

``````(= [1 2 3 4] (list 1 2 3 4))
;=> true``````

Different types, but considered equal

## Symbols

• Usually `lowercase-words-hyphenated`

• Begin with an alphabet character

• Can contain numbers and punctuation

• Identifiers

## Resolving symbols

``inc``
``foo``
``(quote foo)``
``'foo``

`quote` means don’t resolve or evaluate

## Quote also works on lists

``````(quote (1 2))
;=> (1 2)``````
``````'(1 2)
;=> (1 2)``````

Without quote we have a problem:

``````(1 2)
;=> Exception: Long cannot be cast to IFn``````
 Tried to apply 1 as a function
TypeValue
`Long`
`1`
`Double`
`3.14`
`BigInteger`
`1000000000000N`
`BigDecimal`
`1000000000000.1M`
`Exponents`
`1e3`
`Ratio`
`2/5`

## Strings and characters

`"This is a string."`

Characters written with a backslash

```\a \b \c
\newline \tab \space```

## Maps

```{"name" "Fate of the Furious"
"sequence-number" 8
"rotten-tomatoes" 0.66
"imdb" 0.67}```
• Order 1 lookup, "add", "delete" by key

• Tuned to be fast

• Replacement for structs/objects

• Versatile; used often in Clojure code

## Keywords

• `:my-keyword`

• Shorthand identifiers

• Begin with a colon

• Often used as keys in hashmaps

```{:name "Fate of the Furious"
:sequence-number 8
:rotten-tomatoes 0.66
:imdb 0.67}```

## Map operations

``````(get {:a 1} :a)
;=> 1``````
``````(get {:a 1} :b 2)
;=> 2``````
``````(assoc {:a 1} :b 2)
;=> {:a 1, :b 2}``````
``````(dissoc {:a 1} :a)
;=> {}``````

## More map operations

``````(update {:a 2} :a inc)
;=> {:a 3}``````
``````(update {:a [1 2 3]} :a conj 4)
;=> {:a [1 2 3 4]}``````
``````(merge {:a 1} {:b 2})
;=> {:a 1, :b 2}``````

## Commas

Commas are optional and treated as whitespace

```(= {:a 1, :b 2, :c 3}
{:a 1 :b 2 :c 3})```

Prefer newlines

```{:a 1
:b 2
:c 3}```

## Nesting datastructures

```{:name "Fate of the Furious"
:sequence-number 8
:ratings {:rotten-tomatoes 0.66
:imdb 0.67}}```

Ratings are a nested map

```{[1 2] {:name "diamond", :type :treasure}
[3 4] {:name "dragon", :type :monster}}```

A map with vector coordinate keys, and map values

## Nested operations

``````(assoc-in {:a {:b {:c 1}}} [:a :b :d] 2)
;=> {:a {:b {:c 1, :d 2}}}``````
``````(update-in {:a {:b {:c 1}}} [:a :b :c] inc)
;=> {:a {:b {:c 2}}}``````
``(get-in {:a {:b {:c 1}}} [:a :b :c])``

## Sets

`#{1 2 3}`

Near constant time lookup

``````(contains? #{1 2 3} 3)
;=> true``````

## Set operations

``````(conj #{1 2 3} 4)
;=> #{1 2 3 4}``````
``````(disj #{1 2 3} 2)
;=> #{1 3}``````

`union`, `difference` and `intersection` are available in the `clojure.set` namespace

## Namespaces

`src/training/my_namespace.clj`

```(ns training.my-namespace
(:require [clojure.set :as set])
(:import (java.time Instant Duration)))
(set/union #{1 2 3} #{3 4})
=> #{1 2 3 4}```
• The name must match path and filename

• `my-namespace``my_namespace.clj`

• `training.``training/`

## From the REPL

```(require '[clojure.set :as set])
(import
(use 'clojure.set)
(require '[clojure.set :refer :all])```
 Avoid `use` and `:refer :all`
 `ns` works in the REPL!
```(ns my.namespace
(:require [clojure.set :as set]))```

## Programs

• Expressions which are evaluated to results

• If an expression needs to be compiled, it will be

• Can be loaded from files or evaluated dynamically

• Unit of compilation is a form

• Nominate an entry point namespace/function

## Namespaced keywords

`:my.namespace/rect`

Shortcut:

``````::rectangle
;=> :my.namespace/rectangle``````

`::` expands to the current namespace

## Defining functions

``````(defn square [x]
(* x x))
(square 2)
;=> 4``````
``````(defn square
"Multiplies a number by itself"
[x]
(* x x))
(square 2)
;=> 4``````

## Defining Vars

``````(def x 1)
;=> #'my.namespace/x``````
``````x
;=> 1``````
• Global mutable reference

• Use sparingly

• `#'` means `var`

## Accessing a var (not the value)

``````(var x)
;=> #'x``````
``````#'x
;=> #'x``````

## Defining Vars continued

• The symbol `x` resolves to a Var

• Vars are automatically dereferenced when evaluated

• Dereferrencing returns the value associated with the Var

• Avoid using vars like variables

• `defn` is actually `def` with a function value

• Can use `#'x` or `(var x)` to access the Var

## Let

``````(let [x 1]
(inc x))
;=> 2``````
• Bind symbols to values in a scope

• Prefer `let` over `def`

## Destructuring (binding forms)

``````(let [[x y] [1 2]]
(+ x y))
;=> 3``````
• Literal data structure containing symbols

• Matches structure

## Why destructure?

```(defn normalize1 [v]
(let [x (first v)
y (second v)
length (Math/sqrt (+ (* x x) (* y y)))]
[(/ x length) (/ y length)]))```

Avoid extracting substructure manually:

```(defn normalize2 [[x y]]
(let [length (Math/sqrt (+ (* x x) (* y y)))]
[(/ x length) (/ y length)]))```

## Vector structures match any sequence

``````(let [[a b] (list 1 2)]
b)
;=> 2``````

## Strings and Collections (list, vector, set, map) implement seq

``````(seq "abc")
;=> (\a \b \c)``````
``````(seq {:a 1, :b 2, :c 3})
;=> ([:a 1] [:b 2] [:c 3])``````
``````(seq? 8)
;=> false``````
``````(let [[a b] "abc"]
b)
;=> \b``````

## Basic sequences

``````(drop 2 [0 0 0 0])
;=> (0 0)``````
``````(range 5)
;=> (0 1 2 3 4)``````
``````(take 2 "abcd")
;=> (\a \b)``````
• Many sequence oriented functions

• Never modify the original sequence

• Often lazy

## Lazy sequences

Lazy means that the next value in the sequence is only calculated when it is made use of

Stream abstraction; only the currently used item needs to be in memory

Useful for processing files that don’t fit in memory

## For expressions

``````(for [i (range 10)]
(* i i))
;=> (0 1 4 9 16 25 36 49 64 81)``````
``````(for [file ["a" "b" "c"]
rank [1 2]]
(str file rank))
;=> ("a1" "a2" "b1" "b2" "c1" "c2")``````

## For expressions continued

``````(for [i (range 10)
:when (odd? i)
:let [square (* i i)]]
square)
;=> (1 9 25 49 81)``````

## Destructuring in a for expression

``````(let [m {:a 1, :b 2, :c 3}]
(for [[k v] m]
[v k]))
;=> ([1 :a] [2 :b] [3 :c])``````
 Destructuring is available in any binding form

## Variadic functions using `&`

``````(defn sub [& vs]
vs)
(sub 1 2 3 4)
;=> (1 2 3 4)``````
• Variadic means variable number of arguments

• Arity means number of arguments

• We could have just passed a vector instead

## Apply

Calls a function with a sequence of arguments

``````(apply + [1 2 3 4])
;=> 10``````

``````(+ 1 2 3)
;=> 6``````

## Destructuring a map

``````(def x {:a 10
:b 20})
(let [{a :a, b :b} x]
(+ a b))
;=> 30``````
``````(let [{:keys [a b]} x]
(+ a b))
;=> 30``````

## Destructuring strings from a map

``````(def y {"a" 10
"b" 20})
(let [{a "a", b "b"} y]
(+ a b))
;=> 30``````
``````(let [{:strs [a b]} y]
(+ a b))
;=> 30``````

## Destructuring a sequence:

``````(def x (range 5))
(first x)
;=> 0``````
``````(rest x)
;=> (1 2 3 4)``````
``````(let [[a & more] (range 5)]
a)
;=> 0``````
``````(let [[a & more] (range 5)]
more)
;=> (1 2 3 4)``````

## Nested destructuring

``````(def movie {:name "Fate of the Furious"
:sequence-number 8
:ratings {:rotten-tomatoes 0.66
:imdb 0.67}})
(get-in movie [:ratings :imdb])
;=> 0.67``````
``````(let [{{:keys [imdb]} :ratings} movie]
imdb)
;=> 0.67``````

## More destructuring

``````(defn f [{:keys [a b] :as x}]
x)
(f {})
;=> {}``````

## Destructuring with defaults

``````(defn f [{:keys [a b] :or {a "default"}}]
a)
(f {})
;=> "default"``````
``````(defn f [x]
(let [defaults {:a "default"}
{:keys [a b]} (merge defaults x)]
a))
(f {})
;=> "default"``````

Anything following a semicolon is a comment

```; this is an inline comment
;; this is a function level comment```

Less common is the comment form:

`(comment anything)`

Removal of next form `#_`

```#_(this form is removed)
#_#_ (ignored-1) (ignored-2)```
• Temporarily remove a form when debugging code

• Looks like a bug eyes emoji

## Regex

`#"pattern"`
``````(re-seq #"\w+" "the quick brown fox")
;=> ("the" "quick" "brown" "fox")``````

## Exercises

See manual end of section 2

Set up the new namespace called `training.syntax`

`(ns training.syntax)`

Define a var called `message` bound to the string `"greetings"`

``````(def message "greetings")
;=> nil``````

Print out the value of the var `message`

``````(prn message)
;;; "greetings"
;=> nil``````
 `prn` keeps the quotes around strings; `println` does not

Create a `let` binding that binds the symbol `message` to `"well hello there"`, and prints out `message` inside the `let` block:

``````(let [message "well hello there"]
(prn message))
;;; "well hello there"
;=> nil``````

Print out message again, outside of the `let` block:

``````(prn message)
;;; "greetings"
;=> nil``````
 `message` global var is still the original value

Create a let binding that destructures a map and prints the greeting and tone:

``````(def m {:greeting "good morning", :tone "happy"})
(let [{:keys [greeting tone]} m]
(prn greeting tone))
;=> "good morning" "happy"``````

``````(defn hi [{:keys [greeting tone]}]