Upload
michiel-borkent
View
416
Download
0
Embed Size (px)
Citation preview
Func%onalProgrammingInPrac%ce
MichielBorkent@borkdude
HogeschoolUtrechtMay9th2016
Agenda
● Func>onalProgramming● Haskell,Scala,Clojure● FullstackexampleusingClojure
First,whatisFP?
• Firstclassfunc>ons• Purefunc>ons• Immutablevalues• Noorfewsideeffects
Firstclassfunc%ons
Func>onscanbecreatedontheflyscala>valf=(x:String)=>"Hello"+xf:String=>String=<function1>scala>f("World")res10:String=HelloWorld
Firstclassfunc%ons
Func>onscanbepassedaroundasvaluesList("Clojure","Scala","Haskell").map(f)res:List(HelloClojure,HelloScala,HelloHaskell)
Purefunc%ons
Func>onwithsameinputalwaysyieldstheoutput:f(x)==y,always
Notapurefunc%onscala>valf=(i:Int)=>Math.random()*if:Int=>Double=<function1>scala>f(1)res14:Double=0.13536266885499726scala>f(1)res15:Double=0.4086671423543593
Apurefunc%on?
valadd=(x:Int,y:Int)=>x+yadd(1,2)//3
Apurefunc%on?classMutableInt(vari:Int){overridedeftoString=i.toString}valadd=(x:MutableInt,y:MutableInt):MutableInt=>newMutableInt(x.i+y.i)valx=newMutableInt(1)valy=newMutableInt(2)add(x,y)//MutableInt=3
Apurefunc%on?No!Youcannotbuildpurefunc>onswithmutableobjects.add(x,y)//MutableInt=3x.i=2add(x,y)//MutableInt=4add(x,y)doesnotalwaysyieldthesameresult!ThisiswhyweneedimmutablevaluesinFunc>onalProgramming.
Apurefunc%on?List(1,2,3)isimmutable.defaddZero(l:List[Int])=0::laddZero(List(1,2,3))//List(0,1,2,3)
Immutabledatastructures
Int,String,etcarealreadyimmutable0::List(1,2,3)//List(0,1,2,3)Vector(1,2,3):+4//Vector(1,2,3,4)Set(1,2,3)+4//Set(1,2,3,4)Efficientbyre-usingstructureinternally
source:hVp://hypirion.com/musings/understanding-persistent-vector-pt-1
Systemsandimmutability• Eachsystemreceivesamessage
and/orsendsamessage• Muta>ngamessagedoesnot
affectothersystem• Intradi>onalOOreferenceslead
touncontrolledmuta>on,alsocalledspookyac>onatadistance
• YoucanprotectyourselfbyusingValueObjectsorDTOs,buttakeswork
• Immutabledatastructuressolvethisproblem
• Statemodifica>on• Observableac>onExamples:• Modifyingavariable• Wri>ngtoafile
Sideeffects
• Purefunc>onshavenosideeffects• Sideeffectsaredifficulttotest(withoutmocks)• PureFPlanguagesmakesideeffectsexplicit• FPlanguagesisolate/minimizesideeffects
Sideeffects
Wherearethesideeffects?
classProgramextendsApp{varx:Int=1defmutateX={x=(Math.random*100).toInt}mutateXprintln(x)}
Wherearethesideeffects?
classProgramextendsApp{varx:Int=1defmutateX={x=(Math.random*100).toInt}mutateXprintln(x)}
WhyFunc%onalProgramming?
• Makescodeseasiertoreasonabout• Easiertotest• Moreexpressive,lesscode=lessbugs• BeVersuitedforparallellisa>onandconcurrency
ExamplesinHaskell,ScalaandClojure
• DefineanewtypePerson• CreatealistofPersons• Counttotallengthoffirstnameswithlength
greaterthan4hVps://github.com/borkdude/fp-hu-may-2016/blob/master/code
DegreesofFP
Nirvana
Unsafe Safe
Useless
Useful C#, Java
Haskell
Scala Clojure
SQL, Linq
Simon Peyton Jones, FP researcher
LearningFP
ChoosealanguagethatencouragesFPApplytheconceptsinyourfavoritelanguage‘Thinklikeafundamentalist,codelikeahacker’–ErikMeijer
Haskell Pure, lazy, statically typed
Clojure Not pure. FP + Lisp on JVM, dynamically typed
Scala Not pure. FP + (immutable) OO on JVM, statically typed
Haskellresources
Clojureresourceshttp://michielborkent.nl/clojurecursus
ScalaresourcesFunctional Programming in Scala Coursera MOOC
DevelopersloveFP
Source: http://stackoverflow.com/research/developer-survey-2016
CompanieswantFPdevs
Source: http://stackoverflow.com/research/developer-survey-2016
OnceyouknowFP
…youcanapplyandseeiteverywhere
FPatmyjob
• MicroservicesinScala• UIinJavaScriptusingReact,ImmutableJSand
Redux
Clojure
• dynamiclanguage• Lisp• func>onalprogramming• immutabledatastructures• strongconcurrencysupport• embraceshostplajorm(JVM,js)• EDN
Clojureinindustry
hVps://www.youtube.com/watch?v=av9Xi6CNqq4
http://dev.clojure.org/display/community/Clojure+Success+Stories
https://www.youtube.com/watch?v=iUC7noGU1mQ
Dataliterals
Keyword::aVector:[1234]Hashmap:{:a1,:b2}Set:#{1234}List:'(1234)
ExtensibleDataNota%on
{:key1"Bar":key2[123]"key3",#{1.02.0\c}:key4,{:foo{:bar{:baz'hello}}}}(pr-str{:foo"bar"})(read-string"{:foo\"bar\"}")
f(x)->(fx)
Syntax
Syntax
if(...){...}else{->...}
(if.........)
Syntax
varfoo="bar";
(deffoo"bar")
JavaScript-ClojureScript
if(bugs.length>0){return'Notreadyforrelease';}else{return'Readyforrelease';}
(if(pos?(countbugs))"Notreadyforrelease""Readyforrelease")
source:hVp://himera.herokuapp.com/synonym.html
JavaScript-ClojureScript
varfoo={bar:"baz"};foo.bar="baz";foo["abc"]=17;alert('foo')newDate().getTime()newDate().getTime().toString()
(deffoo(js-obj"bar""baz"))(set!(.-barfoo)"baz")(asetfoo"abc"17)(js/alert"foo")(.getTime(js/Date.))(..(js/Date.)(getTime)(toString))
source:hVp://himera.herokuapp.com/synonym.html
Persistentdatastructures
(defv[123])(conjv4);;=>[1234](getv0);;=>1(v0);;=>1
Persistentdatastructures(defm{:foo1:bar2})(assocm:foo2);;=>{:foo2:bar2}(getm:foo);;=>1(m:foo);;=>1(:foom);;=>1(dissocm:foo);;=>{:bar2}
Func%onalprogramming(defr(->>(range10);;(012..9)(filterodd?);;(13579)(mapinc)));;(246810);;ris(246810)
Func%onalprogramming;;ris(246810)(reduce+r);;=>30(reductions+r);;=>(26122030)varsum=_.reduce(r,function(memo,num){returnmemo+num;});
Sequenceabstrac%onDatastructuresasseqs(first[123]);;=>1(rest[123]);;=>(23)Generalseqfunc>ons:map,reduce,filter,...(distinct[1123]);;=>(123)(take2(range10));;=>(01)SeehVp://clojure.org/cheatsheetformore
Sequenceabstrac%onMostseqfunc>onsreturnlazysequences:(take2(map(fn[n](js/alertn)n)(range))) infinitelazysequenceofnumbers
sideeffect
Mutablestate:atoms(defmy-atom(atom0))@my-atom;;0(reset!my-atom1)(reset!my-atom(inc@my-atom));;badidiom(swap!my-atom(fn[old-value](incold-value)))(swap!my-atominc);;same@my-atom;;4
Lisp:macros(mapinc(filterodd?(range10)))(->>(range10)(filterodd?)(mapinc))
threadlastmacro
Lisp:macros(macroexpand'(->>(range10)(filterodd?)));;=>(filterodd?(range10))(macroexpand'(->>(range10)(filterodd?)(mapinc)));;=>(mapinc(filterodd?(range10)))
Lisp:macrosJVMClojure:(defmacrodefonce[xinit]`(when-not(exists?~x)(def~x~init)))
ClojureScript:(defoncefoo1)(defoncefoo2);;noeffect
notes:● macrosmustbewriVeninJVMClojure● areexpandedatcompile>me● generatedcodegetsexecutesinClojureScript
Ar%kelinJavaMagazineoverClojure
hVp://michielborkent.nl/nljug/18_21_Clojure.pdf
Demo%me!https://github.com/borkdude/fp-hu-may-2016