\documentclass{beamer}
\title{Clojure Core}
\subtitle{Primatives, collections, functions, and macros}
\author{Lily Carpenter}
\institute{https://gitlab.com/azrazalea/}
\mode<presentation> {\usetheme{Dresden}}
\date{}

\usepackage[latin1]{inputenc}
\usepackage{times}
\usepackage[T1]{fontenc}
\usepackage[english]{babel}
\usepackage{hyperref}
\usepackage{minted}
\usepackage{upquote}

\AtBeginDocument{%
  \def\PYZsq{\textquotesingle}%
}

\begin{document}

\begin{frame}
  \titlepage
\end{frame}

\begin{frame}
  \frametitle{Summary}
  \tableofcontents
\end{frame}

\section{Primitives}
\begin{frame}
  \frametitle{Primitives}
  Uses host language primitives
  \begin{itemize}
  \item{Integers}
  \item{Floating points}
  \item{Ratios}
  \item{Strings}
  \item{Regexes}
  \item{Keywords}
  \item{Symbols}
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Integers}
  \begin{itemize}
  \item{Standard java Long}
  \item{Automatically upgrade to arbitrary precision BigInteger with certain functions}
  \item{BigInteger does not exist for ClojureScript}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Integers}
  \begin{minted}{clojure}
    (+ 1 1)
    ;=> 2
    (/ 6 3)
    ;=> 2
    (> 3 2 1)
    ;=> false
    (< 3 2 1)
    ;=> true
    (class (+ 1 1))
    ;=> java.lang.Long
  \end{minted}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Integers}
  \begin{minted}{clojure}
    ;; To the more experienced,
    ;; why does this not need +'?
    (class (+ 200000000000000000000
              100000000000000000))
    ;=> clojure.lang.BigInt
  \end{minted}
\end{frame}


\begin{frame}
  \frametitle{Floating points}
  \begin{itemize}
  \item{Standard java Double}
  \item{Automatically upgrade to BigDecimal with certain functions}
  \item{BigDecimal does not exist for ClojureScript}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Floating points}
  \begin{minted}{clojure}
    (+ 0.1 0.1) ; leading zero required
    ;=> 0.2
    (* 0.1 0.1)
    ;=> 0.010000000000000002
    (class (* 0.1 0.1))
    ;=> java.lang.Double
    ;; Note the *', needed to promote doubles
    (class (*' (- 2M 2e-52M) 2e1023M))
    ;=> java.math.BigDecimal
  \end{minted}
\end{frame}

\begin{frame}
  \frametitle{Ratios}
  \begin{itemize}
  \item{Represents fractions without using floating point}
  \item{Standard numeric operations work}
  \item{Automatically reduces}
  \item{Not in clojurescript}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Ratios}
  \begin{minted}{clojure}
    (/ 2 3)
    ;=> 2/3
    (/ 3 6)
    ;=> 1/2
    (+ 1/2 1/2)
    ;=> 1N
    (class (+ 1/2 1/2))
    ;=> clojure.lang.BigInt
    (+ 3/4 0.25)
    ;=> 1.0
    (class (+ 3/4 0.25))
    ;=> java.lang.Double
    (+ 3/4 1)
    ;=> 7/4
  \end{minted}
\end{frame}


\begin{frame}
  \frametitle{Strings}
  \begin{itemize}
  \item{Java strings}
  \item{Common to use Java methods to manipulate}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Strings}
  \begin{minted}{clojure}
    (.toUpperCase "blah")
    ;=> "BLAH"
    (.split "BLAH BLAH BLAH" "")
    ;=> ("BLAH" "BLAH" "BLAH")
    (clojure.string/upper-case "blah")
    ;=> "BLAH"
    (clojure.string/split "BLAH BLAH BLAH" "")
    ;=> ("BLAH" "BLAH" "BLAH")
  \end{minted}
\end{frame}

\begin{frame}
  \frametitle{Regexes}
  \begin{itemize}
  \item{Use either re-pattern or literal syntax}
  \item{Creates java.util.regex.Pattern}
  \item{Use re-seq, re-find, re-matches}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Regex}
  \begin{minted}{clojure}
    (re-seq #"[0-9]+" "abs123def345ghi567")
    ;=> ("123" "345" "567")
    (re-find #"([-+]?[0-9]+)/([0-9]+)" "22/7")
    ;=> ["22/7" "22" "7"]
  \end{minted}
\end{frame}

\begin{frame}
  \frametitle{Keywords}
  \begin{itemize}
  \item{Identifiers that just evaluate to themselves}
  \item{Can be used to lookup keys in maps}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Keywords}
  \begin{minted}{clojure}
    :foo
    ;=> :foo
    (keyword 'foo)
    ;=> :foo
    (:foo {:foo 1})
    ;=> 1
  \end{minted}
\end{frame}

\begin{frame}
  \frametitle{Symbols}
  \begin{itemize}
  \item{"Variables": Not really, but partially serve the same purpose}
  \item{They are identifiers pointing to something else}
  \item{They don't vary (hence not really variables)}
  \item{The actual storage location is called a var, symbol is just a name that points to it}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Symbols}
  \begin{minted}{clojure}
    (symbol 'foo)
    ;=> foo
    (symbol "foo")
    ;=> foo
    (symbol "clojure.core" "foo")
    ;=> clojure.core/foo
    (defn blah
      []
      (println "blah"))
    ;=> #'user/blah
    (let [x 5]
      (+ x 2))
    ;=> 7
  \end{minted}
\end{frame}

\section{Sequences}
\begin{frame}
  \frametitle{Sequences}
  \begin{itemize}
  \item{Generalized interface implemented by most collections.}
  \item{Many functions on sequences are lazy}
  \item{first}
  \item{rest}
  \item{cons}
  \end{itemize}
\end{frame}

\section{Collections}
\begin{frame}
  All persistent(shared structure). Also implement the ISeq interface.
  \frametitle{Collections}
  \begin{itemize}
  \item{Lists}
  \item{Vectors}
  \item{Maps}
  \item{Sets}
  \item{Records}
  \end{itemize}
\end{frame}

\begin{frame}
  \frametitle{Lists}
  \begin{itemize}
  \item{Basic linked list in function}
  \item{Directly implements Sequence interface, except for empty list}
  \item{Conj puts the item at the front of the list}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Lists}
  \begin{minted}{clojure}
    '(1 2 3 4) ; Literal list
    ;=> (1 2 3 4)
    (list 1 2 3 4)
    ;=> (1 2 3 4)
    (+ 1 2) ; List as code structure
    ;=> 3
    (first '(1 2 3 4)) ; Using list as data structure
    ;=> 1
    (rest '(1 2 3 4))
    ;=> (2 3 4)
    (conj '(1 2 3 4) 5)
    ;=> (5 1 2 3 4)
  \end{minted}
\end{frame}

\begin{frame}
  \frametitle{Vectors}
  \begin{itemize}
  \item{Very similar to Arrays in other languages}
  \item{Conj puts the item at the end of the vector}
  \item{Supports rseq function for quick reversal}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Vectors}
  \begin{minted}{clojure}
    [1 2 3 4 5] ; Literal vector
    ;=> [1 2 3 4 5]
    (vector 1 2 3 4 5)
    ;=> [1 2 3 4 5]
    (conj [1 2 3 4] 5)
    ;=> [1 2 3 4 5]
    (rseq [1 2 3 4 5])
    ;=> (5 4 3 2 1)
  \end{minted}
\end{frame}

\begin{frame}
  \frametitle{Maps}
  \begin{itemize}
  \item{Standard key and value pairs}
  \item{Either hashed or sorted}
  \item{Conj expects another Map and merges them}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Maps}
  \begin{minted}{clojure}
    {:key1 1, :key1 2} ; Literal HashMap
    ;=> {:key1 2}
    (hash-map :key1 1, :key1 2)
    ;=> {:key1 2}
    (assoc {} :key1 1)
    ;=> {:key1 1}
    (dissoc {:key1 1} :key1)
    ;=> {}
    (conj {:key1 1} {:key2 2})
    ;=> {:key1 1 :key2 2}
  \end{minted}
\end{frame}

\begin{frame}
  \frametitle{Sets}
  \begin{itemize}
  \item{Unique set of values}
  \item{Either hashed or sorted}
  \item{Conj adds new elements to set}
  \item{Various set operations including union, difference, and intersection.}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Sets}
  \begin{minted}{clojure}
    #{1 2 3} ; Literal HashSet
    ;=> #{1 2 3}
    (hash-set 1 2 3)
    ;=> #{1 2 3}
    (conj #{1 2 3} 4)
    ;=> #{1 2 3 4}
    (disj #{1 2 3} 3)
    ;=> #{1 2}
  \end{minted}
\end{frame}

\begin{frame}
  \frametitle{Basic collection functions}
  \begin{itemize}
  \item{Reduce: Standard functional reduce(fold left), iterate over collection and return a single accumulated result.}
  \item{Map: Standard functional map, iterate over collection and return a Sequence containing one value per a collection item.}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Basic collection functions}
  \begin{minted}{clojure}
    (reduce + [1 2 3 4 5])
    ;=> 15
    (reduce conj #{} [:a :b :c])
    ;=> #{:a :b :c}
    (map inc [1 2 3])
    ;=> (2 3 4)
    (map + [1 2 3] [4 5 6] [7 8 9])
    ;=> (12 15 18)
    (defn wrong-arity-func
      [a b]
      (+ a b))
    (map wrong-arity-func [1 2 3] [4 5 6] [7 8 9])
    ;=> ArityException: Wrong number of args (3)
    ;=> passed to wrong-arity-func
  \end{minted}
\end{frame}

\section{Control Flow}
\begin{frame}
  \frametitle{Looping/recursion}
  \begin{itemize}
  \item{Loop: Provides a lexical closure to recur to.}
  \item{Recur: Used for loop control flow as well as for general recursive functions.}
  \item{Recur will throw an exception if it is not in tail position}
  \item{Quite often your use case can be solved using map/reduce or similar instead.}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Looping/recursion}
  \begin{minted}{clojure}
    (loop [x 10]
      (when (> x 1)
        (println x)
        (recur (- x 2))))
    ;=> 10
    ;=> 2
    (defn count-to-10 [x]
      (when (<= x 10)
        (println x)
        (recur (inc x))))
    (count-to-10 5)
    ;=> 5
    ;=> 10
  \end{minted}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Looping/recursion}
  \begin{minted}{clojure}
    (defn count-to-10 [x]
      (when (<= x 10)
        (recur (inc x))
        (println x)))
    ;=> CompilerException java.lang
    ;=> .UnsupportedOperationException: Can only
    ;=>    recur from tail position
  \end{minted}
\end{frame}

\begin{frame}
  \frametitle{Conditionals}
  \begin{itemize}
  \item{If: Basic if statement, only support true and false branches for one statement. }
  \item{Cond: More complex if, takes many different conditionals.}
  \item{Case: Standard switch case statement}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Conditionals}
  \begin{minted}{clojure}
    (if (even? 6)
      (println true)
      (println false))
    ;=> true
    (if (even? 5)
      (println true)
      (println false))
    ;=> false
    (cond
      (< 5 0) true
      (> 5 0) false
      :else nil)
    ;=> false
  \end{minted}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Conditionals}
  \begin{minted}{clojure}
    (cond
      (< 0 5) true
      (> 0 5) false
      :else nil)
    ;=> true
    (let [mystr "no match"]
      (case mystr
        "" 0
        "hello" (count mystr)
        "default"))
    ;=> "default"
  \end{minted}
\end{frame}

\section{Macros}
\begin{frame}
  \frametitle{Macros}
  Very very very brief(and technically incorrect) explanation is: \\~\\

    A 'function' that does not evaluate its arguments by default and returns
    a list that will then be evaluated as a code form. \\~\\

  Read \url{http://www.braveclojure.com/writing-macros/}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Macros}
  \begin{minted}{clojure}
    (defmacro pointless
      [n]
      n)
    (pointless (+ 1 2))
    ;=> 3
    (pointless 3)
    ;=> 3
    (pointless [1 2 3 4])
    ;=> [1 2 3 4]
  \end{minted}
\end{frame}


\begin{frame}
  \begin{center}
    \Huge Questions?
  \end{center}
\end{frame}
\end{document}
