Here are my notes regarding Clojure; please add things I missed and more important things in the same writing style.

## Basics ##

Clojure
- lisp heritage
    - lisp dialect with functional emphasis
    - well designed thanks to that
    - prefix notation
        - operator comes first
- clojure.jar is the compiler
    - takes code in clojure, compiles to JVM java machine language
- hosted language
    - JVM provides garbage collection and more
- general-purpose language
    - code represented as data structures
    - suited for distributed and parallel computing
    - immutable data, functions, structures

Leiningen
- builds and manages projects for clojure
    - lein new app alkjalf TO create new project
    - lein uberjar TO create new package

REPL
- read evaluate print loop
- quick feedback cycle
- like a local ssh for a running clojure process



## Concepts ##

Immutability
- cannot be changed, altered, modified once created
    - ensures data integrity and consistency
- once created, cannot be modified - any modifications result in a new data structure
    - vectors, maps, sets are data structures that follow immutability
        - created with conj, assoc, hash-map
        - anything that "updates" just returns a new structure with different values
    - functions also immutable
    - immutability can be technically circumvented with atoms but they still follow rules
- def permanently binds a name to a value
    - defn binds a name to a function

Truthiness/Falsiness
- many functions work on interpreting values based on whether they are truthy or falsey

Simplicity
- It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures. —Alan Perlis


** Functional Programming
- Programs based on functions
- 

Concurrency
- software trnsactional memory
    - allows multiple threads to share data without locks
    - creates transaction log
        - if attempt is made to modify, check if data has been modified
        - if so, thread can retry or abort
- concurrency commands for transactions
    - dosync for multiple operations in one transaction
    - ref-set and alter to atomically modify reference
        - ref-set-validator and alter-validator calls function before reference is changed
    - commute to atomically modify without blocking
- STM and macros assist concurrent application development
- writers don't block readers and commuters
- readers don't block writers, other readers, or commuters
- i/o should be avoided in transactions since they will be retried

Debugging
- identify problem
    - LOOK AT REPL, LINE NUMBER IS USUALLY GIVEN
    - examine log files, run tests, use debugging tools
- isolate issue
    - use REPL to evaluate expressions
- fix problem by changing code
- test to make sure it's fixed
- write things step by step not in big chunks
- "ooooo cannot be cast to clojure.lang.IFn" means something that is not a function is trying to be called as one

Lazy Evaluation
- evaluation is delayed until value needed
    - improves performance by avoiding unnecessary computation
    - evaluates a block at a time, only getting what's needed
    - used for infinite data structures
- lazy-seq is the main function, but many functions return lazy sequences
- opposite is eager

Destructuring
- concisely bind names to values in a collection to write more human-readable code
    - eg put brackets or braces the defn parameter
        - (defn get-eggs [{first-egg :egg1 second-egg :egg2}]
        - (println first-egg second-egg))
        - (get-eggs {:egg1 "brown" :egg2 "bluebird"}) => "brownbluebird"
    - can also use [{:keys [egg1 egg2]} :as egg-basket]


## Tools ##

Functions
- takes input, performs operations, returns result
    - can take different inputs and return different results
    - immutable, like everything
        - same input always gives same result
- evaluated at runtime
    - executed while program is running
    - evaluated each time it is called
- function call is an operation where operator is a function
    - or a function expression (expression that returns a function)
- always returns last evaluated form
- all functions, built-in or created, are evaluated the same

Anonymous Functions
- different forms
    - (fn [] body)
    - (def cool-function (fn [] body)) == (defn cool-function [] body)
    - #(body %)
        - % is argument passed in if not defined
            - can do %1 %2 and %& to indicate order of passed functions


Macros
- didn't cover anything about macros yet
- create custom functions to manipulate code at compile time
- can create data structures etc
- can be used to create domain-specific languages
    - express complex operations in a readable way
- can be used to optimize code
    - eliminate unnecessary structures
    - replace with more efficient ones
- create custom control structures
    - eg. looping constructs
- evaluated only once

** Higher Order Functions
- function that wraps over another function and returns a larger function
- 

** Request

** Response

** Dynamic Variables
- 4 different mechanisms for referencing a changing value
- Vars are usually static but can be made dynamic with ^:dynamic and binding (macro)
- Ref is atomic reference type
    - atomic means that every change to Refs made within a transaction occurs or none do
    - isolated (blind to other transactions while running) and consistent (checked with validator)
    - multiple threads can access and modify data safely and consistently
    - managed with transactions
- Agents
- Atoms also allow multiple threads
    - not transactional
    - any changes are immediately visible to all threads

Docstrings
- can be defined with the function or the def

Arity
- functions can be defined to do different things depending on how many parameters are given
- variable numbers of parameters are indicated with &

Let bindings
- provide clarity by letting new names happen
- evaluate expression once, use result for anything
    - important for expensive calculations, side-effect causing i/o etc, or network calls

Regex
- put regex in quotes after a hash mark


## Data Structures ##

Values
- Strings
    - double quotes
    - concatenated with str function
- Numbers
    - represented directly
    - can do integers, floats, ratio/fraction no problem
- Keywords
    - primarily used as keys in maps
    - mostly defined as :key-name but can be anything

Collections
- Vectors
    - [collection of indexed elements]
    - 
    - used when order matters, eg access by index
    - manipulate with first, rest, conj etc
    - index starts at 0
    - conj adds to end
- Sets
    - #{unordered collection of unique elements}
    - used when unique elements are necessary or to remove repeated elements from vector
        - duplicates ignored when adding
    - set operations like union, intersection, difference
    - can check membership with get or contains?
        - get returns value or nil, contains returns true or false
- Maps
    - {:key-value "pairs"}
    - used to efficiently find and organize data associated with an element
    - keys must be unique
        - keys can map to only one value, but the value can also be a collection of more key-value pairs
- Lists
    - '(linear collections of values)
    - conj adds to beginning of list
    - used mostly for macros or if you need to append to start




## Function Notes ##
- when
    - different from if in that it performs multiple operations without needing to use do
- or returns first truthy value or last value
- and returns first falsey value or last value **
- Reduce
    - applies a function to elements of a collection to reduce to a single value
    - flattens out sub-collections