# Clojure - a whirlwind tour

Clojure is a functional, dynamic language, a dialect of Lisp that runs on the JVM. Because it is a functional language, it has some aspects we can talk about:

- Immutable data
- Higher-order function
- Anonymous function
- Recursive
- Lazy evaluation

My first impression is that Clojure exclusively uses prefix notation, instead of infix notation like other popular languages.
For example, to evaluate expression `1 + 2 * 3`

, we must write:

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

All operations in Clojure take the form *opening parenthesis, operator, operands, closing parenthesis*:

```
(max 3 5)
; => 5
(println "result is:" (* 2 4))
```

### Define global var

Clojure has no declared and assigned variable syntax like procedure language, instead, Clojure uses `def`

keyword to define a constant:

```
(def number-of-days 10)
```

## Function definition

The general form of a function definition is:

```
(defn (<function name> [parameters]) <function body>)
```

For example:

```
(defn add [x y]
(+ x y))
```

Calling function

```
(add 3 6)
```

## Anonymous function

An anonymous function (or lambda function) can be created using the `fn`

:

```
(fn [parameters list] <function body>)
```

Calling an anonymous function

```
((fn [x y] (+ x y)) 2 4)
;=> 8
```

We can define an anonymous function and bind it to a name using `def`

keyword

```
(def multiply (fn [a, b] (* a b)))
(multiply 4 5) ;=> 20
```

is equivalent to

```
(defn multiply [a, b] (* a b))
```

## Higher-order function

A Higher-order function is a function that:

- takes one or more functions as arguments.
- returns a function as its result.

In Clojure, some well-known higher-order functions are `map`

, `reduce`

, `filter`

, ...

`map`

function take two arguments: a function and a collection

```
(map inc [2, 4, 5, 8, 9])
;=> (3 5 6 9 10)
```

`reduce`

function is another well-known higher-order function

```
(reduce + (range 10))
;=> 45
```

Compose `reduce`

with `count`

function to calculate averages of numbers in the list:

```
(def sum #(reduce + %))
(def avg #(/ (sum %) (count %)))
(avg [3 4 10])
;=> 8
```

View more about writing and using the higher-order function in Clojure at https://clojure.org/guides/higher_order_functions

## Recursive

Because of immutable data, Clojure doesn't have a built-in `for`

or `while`

loop like imperative languages. In Clojure looping and iteration are replaced/implemented via recursive function calls。
The following code uses recursive to calculate the sum of numbers in a list:

```
(defn recursive-sum [nums]
(if (empty? nums)
0
(+ (first nums) (recursive-sum (rest nums)))
)
)
```

In practice, we should use built-in `reduce`

or `map`

functions to work on collection data:

```
(defn reduce-sum [nums]
(reduce + nums)
)
```

### Tail-call optimization:

Since Clojure runs on top of JVM, and currently the JVM does not support tail recursion, it can not make the tail call optimization. Instead, it provides the `recur`

special operator

```
(defn factorial [n]
(loop [cnt n
acc 1]
(if (< cnt 2) acc
(recur (dec cnt) (* cnt acc)))))
```

## Lazy evaluation

Clojure doesn't not lazy evaluation by default, like Haskell. Instead, Clojure supports lazily evaluated sequences.
Some functions like `clojure.core/lazy-seq`

can be used to produce lazy sequences. For example, the following function produces a lazy sequence of Fibonacci numbers:

```
(defn fib-seq
"Returns a lazy sequence of Fibonacci numbers"
([]
(fib-seq 0 1))
([a b]
(lazy-seq
(cons b (fib-seq b (+ a b))))))
```

Even though this sequence is infinite, taking the first N elements from it does return successfully:

```
(take 12 (fib-seq))
;=> (1 1 2 3 5 8 13 21 34 55 89 144)
```