Funk%onale*Programmierung* op%mal*nutzen* Michael*Sperber* *
Individualso<ware* branchenunabhängig* funk%onale*programmierung* Schulungen,*Coaching* www.ac%vecgroup.de* funk%onalecprogrammierung.de*
Objektorien%erte*Programmierung* Objekt* Nachricht* Objekt* Impera've) Programmierung) Instruk%onen* Methode*
UFOs*in*Java* public class UFO { int x, y; List<Shot> shots; *
UFOs*in*Java* public class Shot { final String description; public Shot(String description) { this.description = description; public String getdescription() { return description; @Override public boolean equals(object o) { if (this == o) return true; if (o == null getclass() = o.getclass()) return false; Shot shot = (Shot) o; return description.equals(shot.description); @Override public int hashcode() { return description.hashcode(); @Override public String tostring() { return "Shot{" + "description='" + description + '\'' + '}';
GeJer*und*SeJer* public class UFO { int x, y; List<Shot> shots; public UFO(int x, int y, List<Shot> shots) { this.x = x; this.y = y; this.shots = shots; public int getx() { return x; public void setx(int x) { this.x = x; public int gety() { return y; public void sety(int y) { this.y = y; public List<Shot> getshots() { return shots; *
UFO*bewegen* public class UFO {... public void move(int deltax, int deltay) { this.x = this.x + deltax; this.y = this.y + deltay;
Schuss*abfeuern* public class UFO {... public Shot fireshot() { int size = this.shots.size(); Shot lastshot = this.shots.get(size - 1); this.shots.remove(size - 1); return lastshot;
Abrüsten* public class UFO {... public void disarm(string description) { Iterator<Shot> it = shots.iterator(); while (it.hasnext()) { Shot shot = it.next(); if (shot.getdescription().equals(description)) it.remove(); *
Iteratoren*
Scala*ist*das*neue*Java** class Shot { final var description: String = null def this(description: String) { this() this.description = description def getdescription: String = { return description... *
Scala*ist*das*neue*Java*...* class UFO { var x: Int = 0 var y: Int = 0 final var shots: List[Shot] = null def this(x: Int, y: Int, shots: List[Shot]) { this() this.x = x this.y = y this.shots = shots def getx: Int = { return x def setx(x: Int) { this.x = x def gety: Int = { return y def sety(y: Int) { this.y = y... *
Das*neue*Java*...* class UFO {... def move(deltax: Int, deltay: Int) { this.x = this.x + deltax this.y = this.y + deltay def fireshot: Shot = { val size = this.shots.size(); val lastshot = this.shots.get(size - 1); this.shots.remove(this.shots.size - 1) return lastshot *
Eine*Welt*von*Objekten* ( *Trustees*of*the*Bri%sh*Museum)*
Impera%ve*Programmierung* room1.exit(elephant) hallway.enter(elephant) hallway.exit(elephant) room2.enter(elephant)
Impera%ve*So<ware*
Gesharter*mu%erbarer*Zustand*
Realität*und*Schnappschuss*
Scala* case class Shot(description: String) *
UFOs*in*Scala* case class UFO(x: Int, y: Int, shots: List[Shot]) { def move(deltax: Int, deltay: Int): UFO = UFO(x+deltaX, y+deltay, shots)... *
Schuss*abfeuern* case class UFO(x: Int, y: Int, shots: List[Shot]) {... def fireshot(): (UFO, Shot) = (this.copy(shots = shots.dropright(1)), shots.last)... *
Abrüsten* case class UFO(x: Int, y: Int, shots: List[Shot]) {... def disarm(description: String) : UFO = this.copy(shots = shots.filter({ shot => shot.description == description })) *
Die*rein*funk%onale*Fab* Scheduler*+*Fab* Scheduler*+*Fab* Schnappschuss* Schnappschuss* Schnappschuss* %me*
Spekula%ve*Simula%on*mit*FP*...*kann*parallel*laufen*
FabCZustand*
Func%onal*Data*Structures* map*&*reconstruc%on* can*run*in*parallel*
Filter*gibt s*auch*in*java*8*...* public class UFO { public void disarm(string description) { this.shots = shots.stream().filter(shot -> shot.getdescription().equals(description)).collect(collectors.tolist()); *
Tests* class UFOSpec extends Specification { "Shooting works" >> { "such that it loses a shot" >> { val u1 = UFO(10, 10, List(Shot("laser"), Shot("torpedo"))) val (u2, _) = u1.fireshot() u1.shots.length 1 must_== u2.shots.length *
ScalaCheck* class UFOSpec extends Specification with ScalaCheck { "Shooting works" >> { "such that it always loses a shot" >> { prop { (u1: UFO) => u1.shots.length > 0 ==> { val (u2, _) = u1.fireshot() u1.shots.length 1 must_== u2.shots.length *
(Interna%onal*Conference*on*Func%onal*Programming,*2000)*
Algebra* "Disarming works" >> { "and is commutative" >> { prop{ (kind1: String, kind2: String, ufo: UFO) => ufo.disarm(kind1).disarm(kind2) must_== ufo.disarm(kind2).disarm(kind1) *
Algebra* a + b = b + a a +(b + c) =(a + b)+c a (b + c) =(a b)+(a c)
Algebra* a \ b = b \ a a \ (b \ c) =(a \ b) \ c a \ (b [ c) =(a \ b) [ (a \ c)
Algebra* a? b = b? a a? (b? c) =(a? b)? c a (b? c) =(a b)? (a c)
Associa%vität* a + b + c a/b/c?)
Algebra*vs.*impera%ve*Programmierung* f(x) =f(x) f(x) == f(x)?)
Algebra*vs.*Programme* f(x) (b + c) (f(x) b)+(f(x) c)?)
Der*Scheduler*und*die*Fab*
Hoffnung*in*der*Fab* Trackin*
Reine*Hoffnung* Lächle?*
Hoffnung*mit*Anweisungen* Lernen*
Hoffnung*mit*Wiedervorlage* Gesündere* Ernährung*
Wiederholte*Hoffnung* Gesündere* Ernährung*
Zerstörte*Hoffnung*
Hoffnung*ist*eine*Monade* (cafepress.com)*
Monadische*Berechnungen* m*
Monaden* trait Monad[M[_]] { def unit[a](a: => A): M[A] def flatmap[a, B] (fa: M[A]) (f: A => M[B]) : M[B]
UFOCgestützte*Berechnungen* case class UFOComputation[A] (run: UFO => (UFO, A)) *
UFOCMonade* object UFOMonad extends Monad[UFOComputation] { * override def unit[a](a: => A) : UFOComputation[A] = UFOComputation({ ufo => (ufo, a) })
UFOCMonade* object UFOMonad extends Monad[UFOComputation] { override def flatmap[a, B] (fa: UFOComputation[A]) (f: A => UFOComputation[B]) : UFOComputation[B] = UFOComputation({ ufo => { val (ufo1, a) = fa.run(ufo) f(a).run(ufo1) }})
Monadische*Opera%onen* def fireshot() : UFOComputation[Shot] = UFOComputation({ ufo => ufo.fireshot() }) def disarm(description: String) : UFOComputation[Unit] = UFOComputation({ ufo => (ufo.disarm(description), ()) }) *
Banale*Opera%onen* def getufo() : UFOComputation[UFO] = UFOComputation({ ufo => (ufo, ufo) }) def setufo(ufo: UFO) : UFOComputation[Unit] = UFOComputation({ ufo => (ufo, ()) }) *
Monadische*Syntax* def fireshot() : UFOComputation[Shot] = for { ufo <- getufo() (ufo1, shot) = ufo.fireshot() _ <- setufo(ufo1) } yield shot
ScalaCheckCGeneratoren*für*UFOs* val shotgenerator = for { desc <- Gen.alphaStr } yield Shot(desc) implicit lazy val arbshot: Arbitrary[Shot] = Arbitrary(shotGenerator) val ufogenerator = for { x <- Gen.choose(-100, 100) y <- Gen.choose(-100, 100) shots <- Gen.containerOf[List, Shot](shotGenerator) } yield UFO(x, y, shots) implicit lazy val arbufo: Arbitrary[UFO] = Arbitrary(ufoGenerator)
ZUSAMMEN) FASSUNG)
Daten*sind*Schnappschüsse*
Eigenscha<en*staJ*Beispiele*
Algebra*bringt s*
Abstrak%on,*Abstrak%on,*Abstrak%on* (Paul*Hudak,*1952C2015)** (Augste*Herbin,* Abstrac%on )*
Mehr*Infos* ac%vecgroup.de* funk%onalecprogrammierung.de* michael.sperber@ac%vecgroup.de* @sperbsen*