89
Introduction to Functional Programming and Clojure Jan-Willem van de Meent

Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

  • Upload
    others

  • View
    22

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Introduction to Functional Programming and Clojure

Jan-Willem van de Meent

Page 2: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(nsexamples.factorial(:gen-class))!(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))!(defn-main[&args](doseq[argargs](let[n(Long/parseLongarg)](println"thefactorialof"arg"is"(factorialn)))))

Anatomy of a Clojure Program

Page 3: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Namespace declaration

Anatomy of a Clojure Program(nsexamples.factorial(:gen-class))!(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))!(defn-main[&args](doseq[argargs](let[n(Long/parseLongarg)](println"thefactorialof"arg"is"(factorialn)))))

Page 4: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(nsexamples.factorial(:gen-class))!(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))!(defn-main[&args](doseq[argargs](let[n(Long/parseLongarg)](println"thefactorialof"arg"is"(factorialn)))))

Recursive function

Anatomy of a Clojure Program

Page 5: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(nsexamples.factorial(:gen-class))!(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))!(defn-main[&args](doseq[argargs](let[n(Long/parseLongarg)](println"thefactorialof"arg"is"(factorialn)))))

Anatomy of a Clojure Program

Main function

Page 6: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

How do I run this?#[email protected]:probprog/ppaml-summer-school-2016.gitcdppaml-summer-school-2016/exercises/!#option1:builduberjarandrunviajavaleinuberjarjava-cptarget/uberjar/examples-0.1.0-SNAPSHOT.jar\ examples.factorial12520!#option2:runusingleiningenleinrun-mexamples.factorial12520!#=>thefactorialof1is1#=>thefactorialof2is2#=>thefactorialof5is120#=>thefactorialof20is2432902008176640000

Page 7: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

How do I run this?#[email protected]:probprog/ppaml-summer-school-2016.gitcdppaml-summer-school-2016/exercises/!#option1:builduberjarandrunviajavaleinuberjarjava-cptarget/uberjar/examples-0.1.0-SNAPSHOT.jar\ examples.factorial12520!#option2:runusingleiningenleinrun-mexamples.factorial12520!#=>thefactorialof1is1#=>thefactorialof2is2#=>thefactorialof5is120#=>thefactorialof20is2432902008176640000

Page 8: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

How do I run this?#[email protected]:probprog/ppaml-summer-school-2016.gitcdppaml-summer-school-2016/exercises/!#option1:builduberjarandrunviajavaleinuberjarjava-cptarget/uberjar/examples-0.1.0-SNAPSHOT.jar\ examples.factorial12520!#option2:runusingleiningenleinrun-mexamples.factorial12520!#=>thefactorialof1is1#=>thefactorialof2is2#=>thefactorialof5is120#=>thefactorialof20is2432902008176640000

Page 9: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

How do I run this?#[email protected]:probprog/ppaml-summer-school-2016.gitcdppaml-summer-school-2016/exercises/!#option1:builduberjarandrunviajavaleinuberjarjava-cptarget/uberjar/examples-0.1.0-SNAPSHOT.jar\ examples.factorial12520!#option2:runusingleiningenleinrun-mexamples.factorial12520!#=>thefactorialof1is1#=>thefactorialof2is2#=>thefactorialof5is120#=>thefactorialof20is2432902008176640000

Page 10: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

$leinrepl#=>nREPLserverstartedonport50240onhost127.0.0.1-nrepl://127.0.0.1:50240#=>REPL-y0.3.7,nREPL0.2.12#=>Clojure1.8.0#=>JavaHotSpot(TM)64-BitServerVM1.8.0-b132#=>Docs:(docfunction-name-here)#=>(find-doc"part-of-name-here")#=>Source:(sourcefunction-name-here)#=>Javadoc:(javadocjava-object-or-class-here)#=>Exit:Control+Dor(exit)or(quit)#=>Results:Storedinvars*1,*2,*3,anexceptionin*e!examples.core=>

Interactive Shell: the REPL

Page 11: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

examples.core=>(require'examples.factorial);;=>nil!examples.core=>(ns'examples.factorial);;=>#object[clojure.lang.Namespace0x42cd2abe"examples.factorial"]!examples.factorial=>(-main"1""2""5""20");;=>thefactorialof1is1;;=>thefactorialof2is2;;=>thefactorialof5is120;;=>thefactorialof20is2432902008176640000;;=>nil

Interactive Shell: the REPL

Page 12: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

$leingorilla

Gorilla REPL

Page 13: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(nsexamples.factorial(:gen-class))!(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))!(defn-main[&args](doseq[argargs](let[n(Long/parseLongarg)](println"thefactorialof"arg"is"(factorialn)))))

Anatomy of a Clojure Function

Page 14: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))!!deffactorial(n):'''computesn*(n-1)*...*1'''ifn==1:return1else:returnn*factorial(n-1)

Anatomy of a Clojure Function

Page 15: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Name(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))!!deffactorial(n):'''computesn*(n-1)*...*1'''ifn==1:return1else:returnn*factorial(n-1)

Anatomy of a Clojure Function

Page 16: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Docstring(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))!!deffactorial(n):'''computesn*(n-1)*...*1'''ifn==1:return1else:returnn*factorial(n-1)

Anatomy of a Clojure Function

Page 17: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Arguments

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))!!deffactorial(n):'''computesn*(n-1)*...*1'''ifn==1:return1else:returnn*factorial(n-1)

Anatomy of a Clojure Function

Page 18: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))!!deffactorial(n):'''computesn*(n-1)*...*1'''ifn==1:return1else:returnn*factorial(n-1)

Function body

Anatomy of a Clojure Function

Page 19: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))!!deffactorial(n):'''computesn*(n-1)*...*1'''ifn==1:return1else:returnn*factorial(n-1)

S-expression

Anatomy of a Clojure Function

Page 20: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

S-expression

Anatomy of a Clojure Function

Block statement

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))!!deffactorial(n):'''computesn*(n-1)*...*1'''ifn==1:return1else:returnn*factorial(n-1)

Page 21: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Anatomy of an Expression

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))

!!!(if(=n1)1(*n(factorial(-n1))))

Page 22: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))

!!!(if(=n1)1(*n(factorial(-n1))))

Anatomy of an Expression

Page 23: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))

!!!(if(=n1)1(*n(factorial(-n1))))

Anatomy of an Expression

Page 24: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))

!!!(if(=n1)1(*n(factorial(-n1))))

Anatomy of an Expression

Page 25: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Anatomy of an Expression

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))

!!!(if(=n1)1(*n(factorial(-n1))))

Page 26: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))

!!!(if(=n1)1(*n(factorial(-n1))))

Anatomy of an Expression

Page 27: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))

!!!(if(=n1)1(*n(factorial(-n1))))

Anatomy of an Expression

Page 28: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))

!!!(if(=n1)1(*n(factorial(-n1))))

Anatomy of an Expression

Page 29: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))

!!!(if(=n1)1(*n(factorial(-n1))))

Anatomy of an Expression

Page 30: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))

!!!(if(=n1)1(*n(factorial(-n1))))

Anatomy of an Expression

Page 31: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))

!!!(if(=n1)1(*n(factorial(-n1))))

Anatomy of an Expression

Page 32: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))

!!!(if(=n1)1(*n(factorial(-n1))))

Anatomy of an Expression

Page 33: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))

!!!(if(=n1)1(*n(factorial(-n1))))

Anatomy of an Expression

Page 34: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))

!!!(if(=n1)1(*n(factorial(-n1))))

Anatomy of an Expression

expression::=symbol|literal|(operator…)

Page 35: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))

!!!(if(=n1)1(*n(factorial(-n1))))

Anatomy of an Expression

expression::=symbol|literal|(operator…)

Page 36: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))

!!!(if(=n1)1(*n(factorial(-n1))))

Anatomy of an Expression

expression::=symbol|literal|(operator…)

Page 37: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))

!!!(if(=n1)1(*n(factorial(-n1))))

Anatomy of an Expression

expression::=symbol|literal|(operator…)

Page 38: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))

!!!(if(=n1)1(*n(factorial(-n1))))

Anatomy of an Expression

expression::=symbol|literal|(operator…)

operator::=special|function|macro

Page 39: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))

!!!(if(=n1)1(*n(factorial(-n1))))

Anatomy of an Expression

expression::=symbol|literal|(operator…)

operator::=special|function|macro

Page 40: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))

!!!(if(=n1)1(*n(factorial(-n1))))

Anatomy of an Expression

expression::=symbol|literal|(operator…)

operator::=special|function|macro

Page 41: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))

!!!(if(=n1)1(*n(factorial(-n1))))

Anatomy of an Expression

expression::=symbol|literal|(operator…)

operator::=special|function|macro

Page 42: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))

!!!(if(=n1)1(*n(factorial(-n1))))

Anatomy of an Expression

expression::=symbol|literal|(operator…)

operator::=special|function|macro

special::=def|if|fn|let|loop|recur|do|new|.|throw|set!|quote|var

Page 43: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))

!!!(if(=n1)1(*n(factorial(-n1))))

Anatomy of an Expression

expression::=symbol|literal|(operator…)

operator::=special|function|macro

special::=def|if|fn|let|loop|recur|do|new|.|throw|set!|quote|var

Page 44: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Atomic !;;symbols(symbol"ada"),ada!;;keywords:ada!;;integers,doubles,ratios1234,1.234,12/34!;;strings,characters"ada",\a\d\a!;;booleans,nulltrue,false,nil!;;regularexpressions#"a*b"

Collections !;;lists(list123),(123)!;;hashmaps{:a1:b2}!;;vectors[123]!;;sets#{123}!;;everythingnests{:a[[12][34]]:b#{56(list78)}:c{"d"9\e10}}

Data Types

Page 45: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Atomic !;;symbols(symbol"ada"),ada!;;keywords:ada!;;integers,doubles,ratios1234,1.234,12/34!;;strings,characters"ada",\a\d\a!;;booleans,nulltrue,false,nil!;;regularexpressions#"a*b"

Collections !;;lists(list123),(123)!;;hashmaps{:a1:b2}!;;vectors[123]!;;sets#{123}!;;everythingnests{:a[[12][34]]:b#{56(list78)}:c{"d"9\e10}}

Data Types

Page 46: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Collections !;;lists(list123),(123)!;;hashmaps{:a1:b2}!;;vectors[123]!;;sets#{123}!;;everythingnests{:a[[12][34]]:b#{56(list78)}:c{"d"9\e10}}

Atomic !;;symbols(symbol"ada"),ada!;;keywords:ada!;;integers,doubles,ratios1234,1.234,12/34!;;strings,characters"ada",\a\d\a!;;booleans,nulltrue,false,nil!;;regularexpressions#"a*b"

Data Types

Page 47: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Evaluation in ClojureClojure Evaluation

Reader

evaluator/compiler

Effect

data structures

Code

Text

bytecode JVM

characters

(image credit: Rich Hickey)

(let[expr(read-string"(+12)")](prnexpr);=>(+12)(prn(classexpr));=>clojure.lang.Persistentlist(prn(class(firstexpr)));=>clojure.lang.Symbol(evalexpr));=>3

Page 48: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Evaluation in ClojureClojure Evaluation

Reader

evaluator/compiler

Effect

data structures

Code

Text

bytecode JVM

characters

(image credit: Rich Hickey)

(let[expr(read-string"(+12)")](prnexpr);=>(+12)(prn(classexpr));=>clojure.lang.Persistentlist(prn(class(firstexpr)));=>clojure.lang.Symbol(evalexpr));=>3

Page 49: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Evaluation in Clojure

(image credit: Rich Hickey)

(let[expr(read-string"(+12)")](prnexpr);=>(+12)(prn(classexpr));=>clojure.lang.Persistentlist(prn(class(firstexpr)));=>clojure.lang.Symbol(evalexpr));=>3

Clojure Evaluation

Reader

evaluator/compiler

Effect

data structures

Code

Text

bytecode JVM

characters

Page 50: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Evaluation in Clojure

(image credit: Rich Hickey)

(let[expr(read-string"(+12)")](prnexpr);=>(+12)(prn(classexpr));=>clojure.lang.Persistentlist(prn(class(firstexpr)));=>clojure.lang.Symbol(evalexpr));=>3

Clojure Evaluation

Reader

evaluator/compiler

Effect

data structures

Code

Text

bytecode JVM

characters

Page 51: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Evaluation in Clojure

(image credit: Rich Hickey)

(let[expr(read-string"(+12)")](prnexpr);=>(+12)(prn(classexpr));=>clojure.lang.Persistentlist(prn(class(firstexpr)));=>clojure.lang.Symbol(evalexpr));=>3

Clojure Evaluation

Reader

evaluator/compiler

Effect

data structures

Code

Text

bytecode JVM

characters

Page 52: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Evaluation in Clojure

(image credit: Rich Hickey)

(let[expr(read-string"(+12)")](prnexpr);=>(+12)(prn(classexpr));=>clojure.lang.Persistentlist(prn(class(firstexpr)));=>clojure.lang.Symbol(evalexpr));=>3

Clojure Evaluation

Reader

evaluator/compiler

Effect

data structures

Code

Text

bytecode JVM

characters

Page 53: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Evaluation in Clojure

(image credit: Rich Hickey)

(let[expr(read-string"(+12)")](prnexpr);=>(+12)(prn(classexpr));=>clojure.lang.Persistentlist(prn(class(firstexpr)));=>clojure.lang.Symbol(evalexpr));=>3

Clojure Evaluation

Reader

evaluator/compiler

Effect

data structures

Code

Text

bytecode JVM

characters

Page 54: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Evaluation in Clojure

(image credit: Rich Hickey)

(let[expr'(+12)](prnexpr);=>(+12)(prn(classexpr));=>clojure.lang.Persistentlist(prn(class(firstexpr)));=>clojure.lang.Symbol(evalexpr));=>6

Clojure Evaluation

Reader

evaluator/compiler

Effect

data structures

Code

Text

bytecode JVM

characters

Page 55: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Evaluation in Clojure

(image credit: Rich Hickey)

(let[expr(quote(+12))](prnexpr);=>(+12)(prn(classexpr));=>clojure.lang.Persistentlist(prn(class(firstexpr)));=>clojure.lang.Symbol(evalexpr));=>6

Clojure Evaluation

Reader

evaluator/compiler

Effect

data structures

Code

Text

bytecode JVM

characters

Page 56: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Macros

(defmacrounless"Inverted'if"[predthenelse](list'ifpredelsethen))

(defflavor:tasty)!(unless(=flavor:tasty):yuk:yum)!;~>(macro-expansion)!(if(=flavor:tasty):yum:yuk)!;=>(evaluation)!:yum

Page 57: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))

Looping

Page 58: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))

Looping

(factorial21);=>ArithmeticExceptionintegeroverflow;clojure.lang.Numbers.throwIntOverflow(Numbers.java:1501)

Page 59: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1N(*n(factorial(-n1)))))

Looping

(factorial21);=>ArithmeticExceptionintegeroverflow;clojure.lang.Numbers.throwIntOverflow(Numbers.java:1501)

Page 60: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*'n(factorial(-n1)))))

Looping

(factorial21);=>ArithmeticExceptionintegeroverflow;clojure.lang.Numbers.throwIntOverflow(Numbers.java:1501)

Page 61: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*'n(factorial(-n1)))))

Looping

(factorial10000);=>StackOverflowErrorclojure.lang.Numbers.equal(Numbers.java:216)

Page 62: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*'n(factorial(-n1)))))

Looping

deffactorial(n):'''computesn*(n-1)*...*1'''ifn==1:return1else:returnn*factorial(n-1)

Page 63: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defn[((

Looping

deffactorial(n):'''computesn*(n-1)*...*1'''result=1foriinrange(2,n+1):result*=ireturnresult

Page 64: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defn[((

Looping

deffactorial(n):'''computesn*(n-1)*...*1'''result=1ivals=range(2,n+1)whileivals:i=ivals.pop(0)result*=ireturnresult

Page 65: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))

Looping

defresultivalsiresult

Page 66: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))

Looping

Start loop

defresultivalsiresult

Page 67: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))

Looping

Initial values

defresultivalsiresult

Page 68: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))

Looping

Any values for i remaining?

defresultivalsiresult

Page 69: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Looping

Compute values for next iteration

(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))

defresultivalsiresult

Page 70: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Looping

Compute values for next iteration

(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))

defresultivalsiresult

Page 71: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))

Looping

Output

defresultivalsiresult

Page 72: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))

Looping

defresultivalsiresult

Page 73: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))

Looping

deffactorial(n):'''computesn*(n-1)*...*1'''result=1ivals=range(2,n+1)whileivals:i=ivals.pop(0)result*=ireturnresult

Page 74: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))

Looping

deffactorial(n):'''computesn*(n-1)*...*1'''result=1ivals=range(2,n+1)whileivals:i=ivals.pop(0)result*=ireturnresult

Page 75: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Looping

(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))

deffactorial(n):'''computesn*(n-1)*...*1'''result=1ivals=range(2,n+1)whileivals:i=ivals.pop(0)result*=ireturnresult

Page 76: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Looping

Passed by value to next iteration

Mutated in place

(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))

deffactorial(n):'''computesn*(n-1)*...*1'''result=1ivals=range(2,n+1)whileivals:i=ivals.pop(0)result*=ireturnresult

Page 77: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Looping

(factorial10000);=>40238726007709377354370243392300398571937486421071463;25437999104299385123986290205920442084869694048004799;88610197196058631666872994808558901323829669944590997;...

(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))

Page 78: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Looping

(factorial10000);=>40238726007709377354370243392300398571937486421071463;25437999104299385123986290205920442084869694048004799;88610197196058631666872994808558901323829669944590997;...

(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))

Can split into separate function

Page 79: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Looping

(defnfloop"innerloopforfactorial"[resultivals](if(seqivals)(floop(*'result(firstivals))(restivals))result))!(defnfactorial[n]"computesn*(n-1)*...*1"(floop1(range2(+n1))))

Page 80: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Looping

(factorial10000);=>StackOverflowError;clojure.lang.Numbers.equal(Numbers.java:216)

(defnfloop"innerloopforfactorial"[resultivals](if(seqivals)(floop(*'result(firstivals))(restivals))result))!(defnfactorial[n]"computesn*(n-1)*...*1"(floop1(range2(+n1))))

Page 81: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Looping

(defnfloop"innerloopforfactorial"[resultivals](if(seqivals)(floop(*'result(firstivals))(restivals))result))!(defnfactorial[n]"computesn*(n-1)*...*1"(floop1(range2(+n1))))

Tail call

Page 82: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Looping

(defnfloop"innerloopforfactorial"[resultivals](if(seqivals)(recur(*'result(firstivals))(restivals))result))!(defnfactorial[n]"computesn*(n-1)*...*1"(floop1(range2(+n1))))

recur allows tail call optimization

Page 83: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Looping

(defnfloop"innerloopforfactorial"[resultivals](if(seqivals)(recur(*'result(firstivals))(restivals))result))!(defnfactorial[n]"computesn*(n-1)*...*1"(floop1(range2(+n1))))

recur allows tail call optimization

(factorial10000);=>40238726007709377354370243392300398571937486421071463;25437999104299385123986290205920442084869694048004799;88610197196058631666872994808558901323829669944590997;...

Page 84: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Looping

(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))

Page 85: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Looping

(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))

Page 86: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Bit-partitioned Hash TriesBit-partitioned hash tries

(image credit: Rich Hickey)

Page 87: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Path Copying

(image credit: Rich Hickey)

Path Copyingint count 15

INode root

HashMapint count 16

INode root

HashMap

Page 88: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Macros

(defmacrodbg"Printsanexpressionanditsvaluefordebugging."[expr](list'do(list'println"[dbg]"(list'quoteexpr)expr)expr))

(dbg(+12));=>[dbg](+12)3;=>3!(macroexpand'(dbg(+12));=>(do;(println"[dbg]";(quote(+12));(+12));(+12))

Page 89: Introduction to Functional Programming and Clojure€¦ · (prn (class expr)) ; => clojure.lang.Persistentlist (prn (class (first expr))) ; => clojure.lang.Symbol (eval expr)) ; =>

Macros

(defmacrodbg"Printsanexpressionanditsvaluefordebugging."[expr]`(let[value#~expr](println"[dbg]"'~exprvalue#)value#))

(dbg(+12));=>[dbg](+12)3;=>3!(macroexpand'(dbg(+12));=>(let*[value__23707__auto__;(+12)];(clojure.core/println;"[dbg]";(quote(+12));value__23707__auto__);value__23707__auto__)