51
Func%onal Programming In Prac%ce Michiel Borkent @borkdude Hogeschool Utrecht May 9 th 2016

Functional Programming In Practice

Embed Size (px)

Citation preview

Page 1: Functional Programming In Practice

Func%onalProgrammingInPrac%ce

MichielBorkent@borkdude

HogeschoolUtrechtMay9th2016

Page 2: Functional Programming In Practice

Agenda

●  Func>onalProgramming●  Haskell,Scala,Clojure●  FullstackexampleusingClojure

Page 3: Functional Programming In Practice

First,whatisFP?

•  Firstclassfunc>ons•  Purefunc>ons•  Immutablevalues•  Noorfewsideeffects

Page 4: Functional Programming In Practice

Firstclassfunc%ons

Func>onscanbecreatedontheflyscala>valf=(x:String)=>"Hello"+xf:String=>String=<function1>scala>f("World")res10:String=HelloWorld

Page 5: Functional Programming In Practice

Firstclassfunc%ons

Func>onscanbepassedaroundasvaluesList("Clojure","Scala","Haskell").map(f)res:List(HelloClojure,HelloScala,HelloHaskell)

Page 6: Functional Programming In Practice

Purefunc%ons

Func>onwithsameinputalwaysyieldstheoutput:f(x)==y,always

Page 7: Functional Programming In Practice

Notapurefunc%onscala>valf=(i:Int)=>Math.random()*if:Int=>Double=<function1>scala>f(1)res14:Double=0.13536266885499726scala>f(1)res15:Double=0.4086671423543593

Page 8: Functional Programming In Practice

Apurefunc%on?

valadd=(x:Int,y:Int)=>x+yadd(1,2)//3

Page 9: Functional Programming In Practice

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

Page 10: Functional Programming In Practice

Apurefunc%on?No!Youcannotbuildpurefunc>onswithmutableobjects.add(x,y)//MutableInt=3x.i=2add(x,y)//MutableInt=4add(x,y)doesnotalwaysyieldthesameresult!ThisiswhyweneedimmutablevaluesinFunc>onalProgramming.

Page 11: Functional Programming In Practice

Apurefunc%on?List(1,2,3)isimmutable.defaddZero(l:List[Int])=0::laddZero(List(1,2,3))//List(0,1,2,3)

Page 12: Functional Programming In Practice

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

Page 13: Functional Programming In Practice

source:hVp://hypirion.com/musings/understanding-persistent-vector-pt-1

Page 14: Functional Programming In Practice

Systemsandimmutability•  Eachsystemreceivesamessage

and/orsendsamessage•  Muta>ngamessagedoesnot

affectothersystem•  Intradi>onalOOreferenceslead

touncontrolledmuta>on,alsocalledspookyac>onatadistance

•  YoucanprotectyourselfbyusingValueObjectsorDTOs,buttakeswork

•  Immutabledatastructuressolvethisproblem

Page 15: Functional Programming In Practice

•  Statemodifica>on•  Observableac>onExamples:•  Modifyingavariable•  Wri>ngtoafile

Sideeffects

Page 16: Functional Programming In Practice

•  Purefunc>onshavenosideeffects•  Sideeffectsaredifficulttotest(withoutmocks)•  PureFPlanguagesmakesideeffectsexplicit•  FPlanguagesisolate/minimizesideeffects

Sideeffects

Page 17: Functional Programming In Practice

Wherearethesideeffects?

classProgramextendsApp{varx:Int=1defmutateX={x=(Math.random*100).toInt}mutateXprintln(x)}

Page 18: Functional Programming In Practice

Wherearethesideeffects?

classProgramextendsApp{varx:Int=1defmutateX={x=(Math.random*100).toInt}mutateXprintln(x)}

Page 19: Functional Programming In Practice

WhyFunc%onalProgramming?

•  Makescodeseasiertoreasonabout•  Easiertotest•  Moreexpressive,lesscode=lessbugs•  BeVersuitedforparallellisa>onandconcurrency

Page 20: Functional Programming In Practice

ExamplesinHaskell,ScalaandClojure

•  DefineanewtypePerson•  CreatealistofPersons•  Counttotallengthoffirstnameswithlength

greaterthan4hVps://github.com/borkdude/fp-hu-may-2016/blob/master/code

Page 21: Functional Programming In Practice

DegreesofFP

Nirvana

Unsafe Safe

Useless

Useful C#, Java

Haskell

Scala Clojure

SQL, Linq

Simon Peyton Jones, FP researcher

Page 22: Functional Programming In Practice

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

Page 23: Functional Programming In Practice

Haskellresources

Page 24: Functional Programming In Practice

Clojureresourceshttp://michielborkent.nl/clojurecursus

Page 25: Functional Programming In Practice

ScalaresourcesFunctional Programming in Scala Coursera MOOC

Page 26: Functional Programming In Practice

DevelopersloveFP

Source: http://stackoverflow.com/research/developer-survey-2016

Page 27: Functional Programming In Practice

CompanieswantFPdevs

Source: http://stackoverflow.com/research/developer-survey-2016

Page 28: Functional Programming In Practice

OnceyouknowFP

…youcanapplyandseeiteverywhere

Page 29: Functional Programming In Practice

FPatmyjob

•  MicroservicesinScala•  UIinJavaScriptusingReact,ImmutableJSand

Redux

Page 30: Functional Programming In Practice
Page 31: Functional Programming In Practice

Clojure

•  dynamiclanguage•  Lisp•  func>onalprogramming•  immutabledatastructures•  strongconcurrencysupport•  embraceshostplajorm(JVM,js)•  EDN

Page 32: Functional Programming In Practice

Clojureinindustry

hVps://www.youtube.com/watch?v=av9Xi6CNqq4

http://dev.clojure.org/display/community/Clojure+Success+Stories

https://www.youtube.com/watch?v=iUC7noGU1mQ

Page 33: Functional Programming In Practice

Dataliterals

Keyword::aVector:[1234]Hashmap:{:a1,:b2}Set:#{1234}List:'(1234)

Page 34: Functional Programming In Practice

ExtensibleDataNota%on

{:key1"Bar":key2[123]"key3",#{1.02.0\c}:key4,{:foo{:bar{:baz'hello}}}}(pr-str{:foo"bar"})(read-string"{:foo\"bar\"}")

Page 35: Functional Programming In Practice

f(x)->(fx)

Syntax

Page 36: Functional Programming In Practice

Syntax

if(...){...}else{->...}

(if.........)

Page 37: Functional Programming In Practice

Syntax

varfoo="bar";

(deffoo"bar")

Page 38: Functional Programming In Practice

JavaScript-ClojureScript

if(bugs.length>0){return'Notreadyforrelease';}else{return'Readyforrelease';}

(if(pos?(countbugs))"Notreadyforrelease""Readyforrelease")

source:hVp://himera.herokuapp.com/synonym.html

Page 39: Functional Programming In Practice

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

Page 40: Functional Programming In Practice

Persistentdatastructures

(defv[123])(conjv4);;=>[1234](getv0);;=>1(v0);;=>1

Page 41: Functional Programming In Practice

Persistentdatastructures(defm{:foo1:bar2})(assocm:foo2);;=>{:foo2:bar2}(getm:foo);;=>1(m:foo);;=>1(:foom);;=>1(dissocm:foo);;=>{:bar2}

Page 42: Functional Programming In Practice

Func%onalprogramming(defr(->>(range10);;(012..9)(filterodd?);;(13579)(mapinc)));;(246810);;ris(246810)

Page 43: Functional Programming In Practice

Func%onalprogramming;;ris(246810)(reduce+r);;=>30(reductions+r);;=>(26122030)varsum=_.reduce(r,function(memo,num){returnmemo+num;});

Page 44: Functional Programming In Practice

Sequenceabstrac%onDatastructuresasseqs(first[123]);;=>1(rest[123]);;=>(23)Generalseqfunc>ons:map,reduce,filter,...(distinct[1123]);;=>(123)(take2(range10));;=>(01)SeehVp://clojure.org/cheatsheetformore

Page 45: Functional Programming In Practice

Sequenceabstrac%onMostseqfunc>onsreturnlazysequences:(take2(map(fn[n](js/alertn)n)(range))) infinitelazysequenceofnumbers

sideeffect

Page 46: Functional Programming In Practice

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

Page 47: Functional Programming In Practice

Lisp:macros(mapinc(filterodd?(range10)))(->>(range10)(filterodd?)(mapinc))

threadlastmacro

Page 48: Functional Programming In Practice

Lisp:macros(macroexpand'(->>(range10)(filterodd?)));;=>(filterodd?(range10))(macroexpand'(->>(range10)(filterodd?)(mapinc)));;=>(mapinc(filterodd?(range10)))

Page 49: Functional Programming In Practice

Lisp:macrosJVMClojure:(defmacrodefonce[xinit]`(when-not(exists?~x)(def~x~init)))

ClojureScript:(defoncefoo1)(defoncefoo2);;noeffect

notes:●  macrosmustbewriVeninJVMClojure●  areexpandedatcompile>me●  generatedcodegetsexecutesinClojureScript

Page 50: Functional Programming In Practice

Ar%kelinJavaMagazineoverClojure

hVp://michielborkent.nl/nljug/18_21_Clojure.pdf

Page 51: Functional Programming In Practice

Demo%me!https://github.com/borkdude/fp-hu-may-2016