This is a study note of the part I: Basics of the book Getting Clojure.
1 Hello Clojure
Some basic examples:
- Use
;
for end of line comment; Use;;
for a comment in its line. (str 3 "2" "hi")
converts its parameters to strings and concatenates them together.(count "string")
counts the length of a string.nil
,true
andfalse
are predfined constants.(println "anything" true false nil)
: prints parameters separted by a space.- basic math operators/functions take a variable number of arguments.
(/ 8 3)
gives8/3
, it has a built-in type ofratio
.(quot 8 3)
to get the quotient.- a commas
,
is a white space in Clojure.
Use def
to bind an identifier to a value. The identifier is called a symbol
in Clojure. Clojure programmers use all-lower-case-kabab-case
to name a symbol. The naming rules for symbols are:
- cannot start with a digit or a colon
:
. The colon is used for keywords. - cannot inlucde special characters such as parentheses, square brackets, braces,
@
and^
. - most characters such as
&
,|
, or-
can be used in a symbol name.
2 Vectors and Lists
- a
vector
is an ordered collections of items that can be of different types. - a
vector
literal is created by putting values inside a pair of brackets or using thevector
function. - functions working with vectors:
count
,nth
,first
- a vector can be called like a function with an index parameter.
- the
rest
returns asequence
represented as items in parentheses or[]
if a vector only has zero or one item. (conj v item)
appends an item and returns a vector.(cons item v)
prepends an item and returns a sequence.()
is an empty listUse a single quote
'
to create non-empty list:'(1, "two", 3.0)
. The'
is used to tell Clojure that this is a list data, not executable code.Use
list
function to create a list.The functions
count
,nth
,first
,rest
work with a list.(conj l item)
create a new list by prepending an item to a list(cons item l)
also prepends an item.A vector is like an array and a list is implemented as a linked list.
It is easy to prepend items to a list and append items to a vector.
Clojure uses
persistent data
to mean the data is immutable and efficient.Programmers mostly use vector except writing code literals.
3 Map and Set
- Map can be called as a funciton, get
nil
if the key doesn’t exist or the key’s value isnil
. - Use
contains?
to check if a key exists. Keyword
is a special type whose names follow the same rules as symbols- Keywords are interned strings that are part of the program
- primarily used as keys in maps
- used as a marker/label/flag
- used as states
- call the keyword like a funciton
assoc
adds elements anddissoc
removes elementskeys
andvals
return keys and values of a mapcount
,first
,rest
treats maps as a collection of two-element vectors.- Use
sorted-map
to have a sorted map. - both map types don’t support
nth
. use
,
to separate map key-value pairsSets are about membership.
Both set and keyword can be called as a function: return the value or a
nil
.Set can have
nil
as its elementUses
contains
to return atrue
/false
of membership
4 Logic
false
andnil
arefalsy
, everything else istruthy
.and
andor
return one truthy or falsy value of their parameters.- Testing functions:
=
,not=
,>
,>=
,<
,<=
. do
evaluates multiple express and return the last value.when
evaluate multiple expressions when the condition is truthy, else returnnil
cond
takess multiple pairs of expressions, use:else
for the catch-all.when
match a single value.- constants in case expression are not evaluated
- the last catch-all is optional but generate an error if no match
try
evalutes all experssion till the firstcatch
throw
raise anclojure.lang.ExceptionInfo
exception usingex-info
funciton.
5 More Capable Functions
- multi-arity function implements filling in defaults for different arities.
- use
[& args]
for varargs or variadic functions. - you can mix multi-arity with variadic.
multimethod
allows you to pick an implementation based on a splitting function. The splitting function can be a custom function, keyword or built-in functions such asclass
.- use
loop
,recur
for recurssive functions. - add docstring after symbol names in function defintion.
- use
:pre
and:post
to check pre and post-conditions
6 Functional Things
- Functional toolkit:
apply
,partial
,complement
,every-pred
. - Function on the fly:
fn
. - Function literal:
#(...)
,%
,%1
,%2
,%3
. - In the wild:
update
,update-in
,assoc-in
.
7 Let
let
is local binding,def
is global and stable binding.let
can have multiple bindings and multiple expressions.if-let
andwhen-let
8 Def, Symbols, and Vars
def
binds a symbol to a value- The
def
binding is stable and global. it is part of the environment. - Symbols are values. Evaluating a symbol gets the bound value. Use
'name
to get a symbol even it is not used in adef
. - A
var
is a binding ofdef
that is accessed by#'symbol-name
. It have methods such as.get
,.sym
. - Use
(def ^:dynamic *dynamic-symbol* value)
to define a dynamic var. - Use
binding [*symbol* value]
to change it in a scope. - Use
set!
to change a dynamic var from inside a binding. - In the wild:
*print-length*
,*1
,*2
,*3
,*e
.
9 Namespaces
- When boot up, the current namespace is
user
. (ns name)
create and set current namespace.- A fully-qualified symbol has a namespace.
- Use
require 'namesapce
or:require namespace
to load a namespaace - Use
:as
to define alias.:refer
pulls vars.:refer :all
pulls all vars. - By convention, a namespace maps a file path.
.
is a folder and-
is_
. *ns*
returns current namespace.ns-map 'name
list all vars;find-ns 'name
get a namespace.namespace
get the namespace of a symbol.- Keywords have a namespace.
- Namespace doesn’t have a hierarchy.
- Namespace loads once. uses
:reload
to reload. Usedefonce
to enforce load once.