Clojure Book Notes
Clojure Book Notes
Project file sample
(defproject second-edition "1.0.0"
:description "Example sources for the second edition of JoC"
:dependencies [[org.clojure/clojure "1.5.1"]
[org.clojure/clojurescript "0.0-2138"]
[org.clojure/core.unify "0.5.3"]
[org.clojure/core.logic "0.8.5"]]
:source-paths ["src/clj"]
:aot [joy.gui.DynaFrame]
:plugins [[lein-cljsbuild "0.3.2"]]
:cljsbuild
{:builds
[{:source-paths ["src/cljs"]
:compiler
{:output-to "dev-target/all.js"
:optimizations :whitespace
:pretty-print true}}
{:source-paths ["src/cljs"]
:compiler
{:output-to "prod-target/all.js"
:optimizations :advanced
:externs ["externs.js"]
:pretty-print false}}]})
apply function
- apply function takes the vector and sends it to a function as arguments
Example:
(def numbers [1 2 3 4 5 6 7 8 9 10])
(apply + numbers)
Polymorphism
- Its done using protocol extension
Example:
(extend-type java.util.List
Concatenatable
(cat [this other]
(concat this other)))
Integer data types
[127 0x7F 0177 32r3V 2r01111111]
;=> [127 127 127 127 127]
- 0x7F is hexadecimal
- 0177 is octadecimal
- 8r177 is octadecimal
- 32r3V is base 32
- 2r01111111 is binary
Rational numers
Example:
22/7
-7/22
1028798300297636767687409028872/88829897008789478784
-103/4
Characters
Example:
\a ; The character lowercase a
\A ; The character uppercase A
\u0042 ; The Unicode character uppercase B
\\ ; The back-slash character \
\u30DE ; The Unicode katakana character ?
Function with multiple number of arguments
(defn make-set
([x] #{x})
([x y] #{x y}))
- The extra arguments are sent as list
(defn arity2+ [first second & more]
(vector first second more))
Blocks
- The scope of the variables is only defined in the block.
(do
(def x 5)
(def y 4)
(+ x y)
[x y])
; Output [5 4]
Local
- This is similar to the Block defined about
(let [r 5
pi 3.1415
r-squared (* r r)]
(println "radius is" r)
(* pi r-squared))
;; radius is 5
;;=> 78.53750000000001
(pos? x)
- Returns true if number is greater than zero
recur
- Makes a recursive call, but if its in the loop then go the start of the loop
- recur can only be used in the tail statements
loop
- loop syntax is similar to the let, having a vector with pairs of variable and its binding value. The loop is also target for recur
quote ; shortcut ‘
- Quote stops the evaluation of the expression
syntax quote ; shortcut `
- Qualifies unqualified symbol
Example:
`map
;=> clojure.core/map
unquote ; shorcut ~
- opposite of quote
Example:
(let [x 2]
`(1 ~x 3))
;=> (1 2 3)
Accessing Java from clojure
Static class members
(Math/sqrt 9)
Namespaces
Current name space is represented by ns
Example:
joy.ch2=> (defn report-ns []
(str "The current namespace is " *ns*))
joy.ch2=> (report-ns)
;=> "The current namespace is joy.ch2"
Call the method from a namespace
name-space/method-name
Load the namespace use :require
(ns joy.req-alias
(:require [clojure.set :as s]))
(s/intersection #{1 2 3} #{3 4 5})
;=> #{3}
Logic
- Everything is clojure is true except false and nil
- Seq returns the nil if the vector is empty
Scope
The names for the function and symbols are same
Regular expression
Example:
#"Test"
Persistence
- The vectors, lists, maps etc are immutable
Sequences
- The sequential include list, vectors and java arrays
- set and map are not sequential
Seqence functions
- first
- rest
Vectorss
- vec function returns vector
- (vec (range 10))
- into function adds more items to vector
(let [my-vector [:a :b :c]]
(into my-vector (range 10)))
;=> [:a :b :c 0 1 2 3 4 5 6 7 8 9]
- vector-of function allow same data-type in the vector
(into (vector-of :int) [Math/PI 2 1.3])
;=> [3 2 1]
(into (vector-of :char) [100 101 102])
;=> [\d \e \f]
- Accessing nth element
(def a-to-j (vec (map char (range 65 75))))
a-to-j
;;=> [\A \B \C \D \E \F \G \H \I \J]
;nth function
;throws exception if vector empty
;supports not found argument
(nth a-to-j 4)
;;=> \E
;get function
;returns nil if empty vector
;supports not found argument
(get a-to-j 4)
;;=> \E
;vector as function
;throws exception if vector empty
;does not supports not found argument
(a-to-j 4)
;;=> \E
- assoc changes the nh element of vector and return new vector
(assoc a-to-j 4 "no longer E")
;=> [\A \B \C \D "no longer E" \F \G \H \I \J]
- replace function replaces multiple items
(replace {2 :a, 4 :b} [1 2 3 2 3 4])
;=> [1 :a 3 :a 3 :b]
- assoc-in, get-in and update-in changes items in nested structures
Understanding thead macors
Understanding Clojure’s thread macros
- Use thread last (-») macro for sequences
- Use thread first (->) macro for objects (getter and setter)
- We can use three (,,,) for the replacement arguments for readability
- Clojure.walk/macroexpand-all expand the macro
- We can use comment reader macro (#_) to comment part of thread macro
- We can start with thread first and switch to thread last but if you start with thread last then to switch to thread first we need to use anonymous functions.
Understanding list comprehension in Clojure
Understanding list comprehension in Clojure
Examples:
(defn listcomprehension
[]
(count (for [tumbler-1 (range 10)
tumbler-2 (range 10)
tumbler-3 (range 10)
:when (and (or (= tumbler-1 4)
(= tumbler-2 4))
(= tumbler-3 4))]
[tumbler-1 tumbler-2 tumbler-3])))
(defn ticket-number
[]
(def blacklisted #{\I \O})
(def capital-letters (map char (range (int \A) (inc (int \Z)))))
(for [letter-1 capital-letters
letter-2 capital-letters
:when (and (not (blacklisted letter-1))
(not (blacklisted letter-2)))]
(str letter-1 letter-2)))