Introduction to Functional Programming and Clojure
Jan-Willem van de Meent
(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
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)))))
(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
(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
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
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
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
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
$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
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
$leingorilla
Gorilla REPL
(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
(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
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
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
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
(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
(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
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)
Anatomy of an Expression
(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))
!!!(if(=n1)1(*n(factorial(-n1))))
(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))
!!!(if(=n1)1(*n(factorial(-n1))))
Anatomy of an Expression
(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))
!!!(if(=n1)1(*n(factorial(-n1))))
Anatomy of an Expression
(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))
!!!(if(=n1)1(*n(factorial(-n1))))
Anatomy of an Expression
Anatomy of an Expression
(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))
!!!(if(=n1)1(*n(factorial(-n1))))
(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))
!!!(if(=n1)1(*n(factorial(-n1))))
Anatomy of an Expression
(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))
!!!(if(=n1)1(*n(factorial(-n1))))
Anatomy of an Expression
(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))
!!!(if(=n1)1(*n(factorial(-n1))))
Anatomy of an Expression
(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))
!!!(if(=n1)1(*n(factorial(-n1))))
Anatomy of an Expression
(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))
!!!(if(=n1)1(*n(factorial(-n1))))
Anatomy of an Expression
(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))
!!!(if(=n1)1(*n(factorial(-n1))))
Anatomy of an Expression
(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))
!!!(if(=n1)1(*n(factorial(-n1))))
Anatomy of an Expression
(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))
!!!(if(=n1)1(*n(factorial(-n1))))
Anatomy of an Expression
(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…)
(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…)
(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…)
(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…)
(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
(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
(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
(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
(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
(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
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
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
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
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
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
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
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
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
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
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
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
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
Macros
(defmacrounless"Inverted'if"[predthenelse](list'ifpredelsethen))
(defflavor:tasty)!(unless(=flavor:tasty):yuk:yum)!;~>(macro-expansion)!(if(=flavor:tasty):yum:yuk)!;=>(evaluation)!:yum
(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))
Looping
(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*n(factorial(-n1)))))
Looping
(factorial21);=>ArithmeticExceptionintegeroverflow;clojure.lang.Numbers.throwIntOverflow(Numbers.java:1501)
(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1N(*n(factorial(-n1)))))
Looping
(factorial21);=>ArithmeticExceptionintegeroverflow;clojure.lang.Numbers.throwIntOverflow(Numbers.java:1501)
(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*'n(factorial(-n1)))))
Looping
(factorial21);=>ArithmeticExceptionintegeroverflow;clojure.lang.Numbers.throwIntOverflow(Numbers.java:1501)
(defnfactorial"computesn*(n-1)*...*1"[n](if(=n1)1(*'n(factorial(-n1)))))
Looping
(factorial10000);=>StackOverflowErrorclojure.lang.Numbers.equal(Numbers.java:216)
(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)
(defn[((
Looping
deffactorial(n):'''computesn*(n-1)*...*1'''result=1foriinrange(2,n+1):result*=ireturnresult
(defn[((
Looping
deffactorial(n):'''computesn*(n-1)*...*1'''result=1ivals=range(2,n+1)whileivals:i=ivals.pop(0)result*=ireturnresult
(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))
Looping
defresultivalsiresult
(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))
Looping
Start loop
defresultivalsiresult
(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))
Looping
Initial values
defresultivalsiresult
(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))
Looping
Any values for i remaining?
defresultivalsiresult
Looping
Compute values for next iteration
(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))
defresultivalsiresult
Looping
Compute values for next iteration
(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))
defresultivalsiresult
(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))
Looping
Output
defresultivalsiresult
(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))
Looping
defresultivalsiresult
(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
(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
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
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
Looping
(factorial10000);=>40238726007709377354370243392300398571937486421071463;25437999104299385123986290205920442084869694048004799;88610197196058631666872994808558901323829669944590997;...
(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))
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
Looping
(defnfloop"innerloopforfactorial"[resultivals](if(seqivals)(floop(*'result(firstivals))(restivals))result))!(defnfactorial[n]"computesn*(n-1)*...*1"(floop1(range2(+n1))))
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))))
Looping
(defnfloop"innerloopforfactorial"[resultivals](if(seqivals)(floop(*'result(firstivals))(restivals))result))!(defnfactorial[n]"computesn*(n-1)*...*1"(floop1(range2(+n1))))
Tail call
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
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;...
Looping
(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))
Looping
(defnfactorial[n]"computesn*(n-1)*...*1"(loop[result1ivals(range2(+n1))](if(seqivals)(recur(*'result(firstivals))(restivals))result)))
Bit-partitioned Hash TriesBit-partitioned hash tries
(image credit: Rich Hickey)
Path Copying
(image credit: Rich Hickey)
Path Copyingint count 15
INode root
HashMapint count 16
INode root
HashMap
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))
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__)