Transcript
Page 1: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Januar 2011

Dr. Klaus Alfert Dr. Bernd Löchner

Folie 1

Jenseits von Fakultät und Fibonacci: Architektur Funktionaler Programme

Dr. Klaus Alfert Dr. Bernd Löchner

Page 2: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner
Page 3: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Januar 2011

Dr. Klaus Alfert Dr. Bernd Löchner

Folie 3

Warum ist Funktionale Programmierung in vieler Munde?

Page 4: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Sun T 2 »Niagara 2« 2007, 8 Cores × 8 Threads

Page 5: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Intel i7 »Nehalem« 2008, 4 Cores × 2 Threads

Page 6: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

IBM POWER 7, 2010, 8 Cores × 4 Threads

Page 7: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Oracle T 3 »Rainbow Falls« 2010, 16 Cores × 8 Threads

Page 8: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Intel Cloud Computing on a Chip 2009, 48 Cores (Prototyp)

Page 9: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Januar 2011

Dr. Klaus Alfert Dr. Bernd Löchner

Folie 9

Warum ist Nebenläufigkeit mit Objekten schwierig?

Page 10: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Objekte haben eine Identität

:2 :3

:1

Page 11: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Objekte haben einen (lokalen) Zustand

:2 :3

:1

Page 12: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Objekte haben Verhalten

:2 :3

:1

Page 13: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Multithreading erfordert Locks

:2 :3

:1

Page 14: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Ein hoher Grad an Nebenläufigkeit wird leicht unübersichtlich

:2 :3

:1

Page 15: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Ein hoher Grad an Nebenläufigkeit wird leicht unübersichtlich

:2 :3

:1

Page 16: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Wie kann funktionale Programmierung hier helfen?

Page 17: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Januar 2011

Dr. Klaus Alfert Dr. Bernd Löchner

Folie 17

Was unterscheidet FP von OOP?

Page 18: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Zu den Programmbeispielen

Beispiele in Haskell & Erlang

• Haskell ist puristisch elegant

• Erlang hat Industrial-Strength

Die Beispiele sind aber alle übertragbar in andere funktionale Programmiersprachen. F#

Page 19: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

A LISP programmer knows the value of everything, but

the cost of nothing.

–Alan J. Perlis Epigrams of Programming

Page 20: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Werte, Variablen, Veränderliche

Was sind imperative Variablen?

• Namen für Adressen von Speicherzellen

• Abstraktionsniveau: Assembler

• Objekte haben eine Identität: Entspricht einer Adresse von Speicherzellen

Was sind funktionale Variablen?

• Namen für Werte: „Sei x beliebig, aber fest“

• Variablen werden an Werte „gebunden“

• Abstraktionsniveau: Mathematik

• Notwendig: Effiziente Abbildung auf Speicherzellen durch Laufzeitsystem

42

42

x

x

Page 21: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Objekte versus Werte

:1 42 :1 42 :1 42

Funktionen erzeugen aus alten Werte neue!

:2 42 42 42

Copy Gleich, aber nicht identisch

Gleich und identisch

Page 22: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Page 23: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Rekursion statt Iteration: Hyper-Fakultät (Sloane: A Handbook of Integer Sequences)

Fakultät ist für Kinder – Hyper-Fakultät ist für Erwachsene

H(n) = 1, 1, 4, 108, 27648, 86400000, 4031078400000, 3319766398771200000, 55696437941726556979200000, 21577941222941856209168026828800000, 215779412229418562091680268288000000000000000, 61564384586635053951550731889313964883968000000000000000, …

n

k

kknH1

)(

Page 24: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Rekursion statt Iteration: Hyper-Fakultät (Sloane: A Handbook of Integer Sequences)

Imperativ: Zuweisungsorientiert

hfac(n): r := 1; while n > 0 do r := r * n^n; n := n – 1; od return r;

Rekursiv: Werteorientiert

hfac(n)-> if n == 0 then 1 else n^n * hfac(n-1)

Page 25: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Rekursion statt Iteration: Hyper-Fakultät (Sloane: A Handbook of Integer Sequences)

Imperativ: Zuweisungsorientiert

hfac(n): r := 1; while n > 0 do r := r * n^n; n := n – 1; od return r;

Berechnung: hfac(3)

3 n

? r 1 27

2

108

1

108

0

Page 26: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Rekursion statt Iteration: Hyper-Fakultät (Sloane: A Handbook of Integer Sequences)

Imperativ: Zuweisungsorientiert

hfac(n): r := 1; while n > 0 do r := r * n^n; n := n – 1; od return r;

Rekursiv: Werteorientiert

hfac(n)-> if n == 0 then 1 else n^n * hfac(n-1)

Page 27: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Rekursion statt Iteration: Hyper-Fakultät (Sloane: A Handbook of Integer Sequences)

Berechnung:

Rekursiv: Werteorientiert

hfac(n)-> if n == 0 then 1 else n^n * hfac(n-1)

if n == 0 then 1 else n^n * hfac(n-1)

3 n fun

hfac(3)

if n == 0 then 1 else n^n * hfac(n-1)

2 n fun

if n == 0 then 1 else n^n * hfac(n-1)

1 n fun

hfac(2)

hfac(1)

hfac(0)

if n == 0 then 1 else n^n * hfac(n-1)

0 n fun

1 1

1

4

108

Page 28: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Komplexe Werte sind oft baumartig

D11

D112 D111

C D A B

C1 C2

C21 C22 D12

D122 D121

D1

{ vorname : „Martin“, nachname : „Mustermann“, anschrift : { strasse : „Hauptstrasse 23“, ort : { plz : „76541“, stadt : „Neustadt“ } }, kurse : [ { id : „Mo1“, title: „Tutorial C#“ }, { id : „Ndo4“, title: „Architektur“ } ] }

Page 29: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Wie ändert man komplexe Werte?

5

8 3

15

20

21 18

26

27 25

28

35

41 33

24

update (Tree, Value) Tree

Page 30: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Update: Ersetze 41 durch 42

5

8 3

15

20

21 18

26

27 25

28

35

41 33

24

28

24

35

42

Alter Baum Neuer Baum

Beide Bäume existieren gleichzeitig!

Page 31: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Pattern Matching

sum ([]) -> 0; sum ([X | Xs]) -> X + sum (Xs).

abs (N) when N >= 0 -> N; abs (N) -> -N.

length [] = 0 length (x:xs) = 1 + length xs

zip [] _ = [] zip _ [] = [] zip (x:xs) (y:ys) = (x,y) : zip xs ys

Page 32: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Higher-order Funktionen, Polymorphie und Lambda-Ausdrücke

map :: (a -> b) -> [a] -> [b]

map f [] = []

map f (x:xs) = f x : map f xs

map abs [-2 .. 2]

>> [2, 1, 0, 1, 2]

map (\x -> x*x) [-2 .. 2]

>> [4, 1, 0, 1, 4]

Page 33: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Algebraische Datenstrukturen

data Tree a = Empty

| Node (Tree a) a (Tree a)

mapTree :: (a -> b) -> Tree a -> Tree b

mapTree f Empty = Empty

mapTree f (Node l x r) =

Node (mapTree f l) (f x) (mapTree f r)

data Color = Green | Red | ...

autumn t = mapTree change t

where change Green = Red

change c = c

Page 34: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Erlang hat Closures – und Clojure auch (und Scala, F#, …)

mk_mul_abs (M) -> fun (N) when N > 0 -> M * N; (N) -> M * (-N) end.

Ma3 = mk_mul_abs (3). lists:map(Ma3, [-2, -1, 0, 1, 2]).

>> [6, 3, 0, 3, 6]

when N > 0 -> M * N; M * (-N)

3

N fun

mk_mul_abs M

Ma3

Page 35: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Haskell erlaubt Partial Application

parabola a b c x = a*x^2 + b*x + c

p1 :: Double -> Double

p1 = parabola 4.2 -2.0 3.5

y = p1 1.0

linear = parabola 0.0

l1 = linear 3.0 2.1

a*x^2 + b*x + c

3.5 x fun

fun c

p1 fun b

a fun

-2.0

4.2

a*x^2 + b*x + c

x c b a fun

Page 36: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Programmierung im Großen

Verantwortlichkeiten bündeln

• Module, APIs und Interfaces

• Kontrakte: Daten, Funktionen, Eigenschaften

Information Hiding

• Sichtbarkeiten, Namespaces

• Implementierungsinterna verbergen

Wie in OOP:

Benötigt Augenmaß und Disziplin

Beispiel: Pattern Matching

Werteorientierung und Higher-order Funktionen

ermöglichen andere Schnittstellen und Kontrakte

Page 37: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Funktionale Programmierung = Werteorientierung & Higher-order Funktionen

Page 38: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Welche Auswirkungen hat Funktionale Programmierung auf Architektur und Design?

Page 39: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Eoin Wood: Software architecture is the set of design decisions which, if made incorrectly, may cause your project to be canceled.

Page 40: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Grady Booch: Architecture represents the significant design decisions that shape a system, where significant is measured by cost of change.

Page 41: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

ANSI/IEEE 1471-2000 The fundamental organization of a system, embodied in its components, their relationships to each other and the environment, and the principles governing its design and evolution.

Page 42: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

ANSI/IEEE 1471-2000 The fundamental organization of a system, embodied in its components, their relationships to each other and the environment, and the principles governing its design and evolution.

Page 43: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

High-Level Architektur

Page 44: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Architektur auf Marketing-Niveau: Ein typisches „Marchitecture“-Diagramm

DB

System im Fokus

DWH

CRM Server

Auftrags-verwaltung

Kunden-verwaltung

Pricing Logistik

Page 45: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Enterprise Architektur: Funktionalität bleibt lokal, Kommunikation über Werte

DB

System im Fokus

DWH

CRM Server

Auftrags-verwaltung Kunden-

verwaltung

Pricing Logistik HTML

JSON/REST

QuerySet

AMQP

SOAP

Service Bus

Portal Server

MQ SOAP

Host

SOAP

Page 46: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

High Level Architektur: Grobzerlegung bleibt bestehen

Treiber:

• Primär fachliche Zerlegung in Aufgaben- und Verantwortlichkeitsgebiete

• Reflektiert auch die Organisation (Conway’s Law)

Konsequenzen

• Architektur auf dieser Ebene ist unabhängig von der Implementierungstechnologie

• Interna der Komponenten/Subsysteme sind irrelevant

• Kommunikation erfolgt über Werte, Funktionen bleiben lokal und werden nicht transportiert

Page 47: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Mittlere Architektur

Page 48: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Mittlere Architektur: Geprägt von nicht-funktionalen Systemanforderungen

Portabilität Wartbarkeit

Funktionalität

Zuverlässig- keit

Bedienbarkeit

Effizienz Dokumentation

Machbarkeit

Gliederung gemäß ISO/IEC 9126

Page 49: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Enterprise Java

Page 50: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Ein Blick auf Enterprise Java

Historisch:

• Transaktionsmonitor für verteilte Objekte

• Anbindung an (Legacy)-Datenbanken

Ausgelegt für

• Informationssysteme

• Hohen Durchsatz

• Skalierbarkeit

PortabilitätWartbarkeit

Funktionalität

Zuverläs-sigkeit

Bedienbarkeit

EffizienzDoku-

mentationMachbarkeit

Page 51: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Struktur: N-Tier-Schichtenarchitektur

http://download.oracle.com/javaee/6/tutorial/doc/bnaay.html

Page 52: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Einfluss von Java

Everything is an Object

• Auch für Dinge, die eigentlich keine Objekte sind (Stateless Session Beans, MDB, Backing Beans, Servlets, Transaktionen)

Transparente Remote-Aufrufe (RMI)

Thread-Management nur im Container

• Das Lock-Model von Java erlaubt keine Komposition von Concurrent Libraries

Interfaces anstatt abstrakter Klassen

Page 53: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Erlang/OTP

To Iterate is Human, to Recurse Divine – L. Peter Deutsch

Page 54: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Ein Blick auf Erlang/OTP

Historisch:

• Soft-Realtime Systeme, PBX, Telco

Ausgelegt für

• (sehr hohe) Zuverlässigkeit und Fehlertoleranz

• Skalierbarkeit mit massiver Parallelität

• Kommunikationssysteme

Anwendungsbeispiele

• Diverse Telco-Systeme von Ericsson

• Ejabberd, RabbitMQ, CouchDB PortabilitätWartbarkeit

Funktionalität

Zuverläs-sigkeit

Bedienbarkeit

EffizienzDoku-

mentationMachbarkeit

Page 55: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

OTP besteht aus lose gekoppelten „Anwendungen“ …

Anwendung Web Server

odbc

crypto

gen_tcp

uses

Page 56: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

… und aus Supervisor-Prozesshierarchien

Anwendung

Supervisor

Worker Supervisor

Worker Worker überwacht

Page 57: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Einfluss von Erlang auf OTP

Erlang stellt die Basismechanismen bereit

• Pure Funktionen, Datenstrukturen sind immer Werte

• Nebenläufigkeit durch Prozesse – Prozesse sind referenzierbar Entitäten im Sinne von Domain Driven Design

– Halten lokalen State, teilen sich aber keinen State!

• Massive Parallelität durch leichtgewichtige Prozesse und asynchrones Messaging

• Monitoring von Prozessen über VM-Grenzen hinaus

• Hot-Code Swapping: Updates im laufenden System

Nachbau in Scala: Akka (www.akka.io)

Page 58: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Mittlere Architektur: Domäne der Blue-Print-Architekturen

Standardarchitektur für eine bestimmte Systemklasse

• Anwendungsdomäne und -typ sind relevant

• Abgestimmt auf Hardware und Infrastruktur

Geprägt von den nicht-funktionalen Anforderungen

• Priorisierung und Balancierung der Qualitätsattribute

Das technisch Machbare bestimmt den Lösungsraum

• Programmiersprachen

• Laufzeitsysteme

• Bibliotheken PortabilitätWartbarkeit

Funktionalität

Zuverlässig-keit

Bedienbarkeit

EffizienzDokumentation

Machbarkeit

PortabilitätWartbarkeit

Funktionalität

Zuverlässig-keit

Bedienbarkeit

EffizienzDokumentation

Machbarkeit

Page 59: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Kleinteilige Architektur

Page 60: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Page 61: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Peter Norvig: Design Patterns in Dynamic Languages (1998) Analyse der Design Patterns aus Lisp/Dylan-Sicht

• GoF verwendet C++ und Smalltalk

Unterscheidung von Implementierungsebenen

• Unsichtbar: Wird von der Sprache abgedeckt

• Informell: Wird jedes mal neu implementiert

• Formell: Implementierung mit Template oder Macro

Norvigs Fazit für die 23 GoF Patterns:

• 16 werden deutlich einfacher oder unsichtbar

Page 62: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

GoF Command Pattern

http

://e

n.w

ikip

edia

.org

/wik

i/Co

mm

and_

patte

rn

Page 63: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Ein Command ist eine Closure

shutdown_command(Receiver) -> fun() -> Receiver ! {shutdown, now} end.

@Client: MyMachine = …, Cmd = shutdown_command(MyMachine),

add_action(Cmd, Target),

@Target: ... Cmd().

Receiver ! {shutdown, now}

MyMachine

() fun

fun Receiver

Cmd

Page 64: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Commands mit Undo sind Closures mit Pattern Matching

start_command(Receiver) -> fun(do) -> Receiver ! {start, now}; (undo) -> Receiver ! {shutdown, now} end.

@Client MyMachine = …, Cmd = start_command(MyMachine),

@Target ... Cmd(do), ... Cmd(undo).

Receiver ! {start, now}

MyMachine

(do) fun

fun Receiver

Cmd

Receiver ! {shutdown, now}

(undo)

Page 65: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

GoF Visitor Pattern

Ein Composite

http

://e

n.w

ikip

edia

.org

/wik

i/Vi

sito

r_pa

ttern

“Languages that support double- or multiple dispatch lessen the need for the Visitor pattern.

(CLOS actually supports multiple dispatch).” [GoF: p.339]

Page 66: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Composite = Algebraischer Datentyp Visitor = Durchlauf der Struktur

data CarElement = Car [CarElement] | Wheel String | Body | Engine

toString Body = ["Visit Body"] toString Engine = ["Visit Engine"] toString (Wheel s) = ["Visit Wheel " ++ s] toString (Car es) = concat (map toString es) ++ ["Visit Car"]

doCar Body = ["Moving my Body"] doCar Engine = ["Starting my Engine"] doCar (Wheel s) = ["Kicking Wheel " ++ s] doCar (Car es) = concat (map doCar es) ++ ["Starting my Car"]

Die Java Implementierung bei Wikipedia braucht dafür ca. 100 Zeilen

Page 67: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Charakteristik der GoF Patterns (1)

Creational Patterns

• Factories und Builder lösen allgemeine Probleme, unabhängig von OO, auch in C, Modula2, Haskell, Erlang

• Prototypen und Singletons verschwinden

Structural Patterns

• Interface-Probleme und -Lösungen sind sprachunabhängig (Facade, Bridge, Adapter, Proxy)

• Composite und Decorator werden unsichtbar

Page 68: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Charakteristik der GoF Patterns (2)

Behavioral Patterns

• Können durch Lambdas, Pattern Matching, … anders realisiert werden.

• Einige werden unsichtbar, andere sind nicht immer offensichtlich umzusetzen.

Generelle Beobachtung:

• Patterns, die auf Objektidentitäten basieren, müssen ganz anders umgesetzt werden.

Page 69: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Januar 2011

Dr. Klaus Alfert Dr. Bernd Löchner

Folie 69

Funktionale Patterns

http://www.flickr.com/photos/robbie73/

Page 70: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Standardisierte Rekursion

Listenfunktionen in Haskell:

sum [] = 0 sum (x:xs) = x + sum xs

product [] = 1 product (x:xs) = x * product xs

allTrue [] = True allTrue (x:xs) = x && allTrue xs

Extrahiere das Rekursionsschema

foldList startVal combFct [] = startVal foldList startVal combFct (x:xs) = combFct x (foldList startVal combFct xs)

sum = foldList 0 (+)

product = foldList 1 (*)

allTrue = foldList True (&&)

Page 71: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Standardisierte Rekursion

Mit foldList können viele Listenfunktionen implementiert werden

length [] = 0 length (x:xs) = 1 + length xs

map f [] = [] map f (x:xs) = f x : map f xs

length = foldList 0 cFct where cFct x len = 1 + len

map f = foldList [] cFct where cFct x ys = f x : ys

Page 72: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Standardisierte Rekursion für Algebraische Datentypen

Generalisiere für andere Datenstrukturen data Tree a = Empty

| Node (Tree a) a (Tree a)

foldTree eVal cFct Empty = eVal

foldTree eVal cFct (Node l x r) =

cFct (foldTree eVal cFct l) x (foldTree eVal cFct r)

sumTree = foldTree 0 cFct where cFct sl x sr = sl + x + sr

mapTree f = foldTree Empty cFct where cFct ml x mr = Node ml (f x) mr

heightTree = foldTree 0 cFct where cFct hl x hr = 1 + max hl hr

Page 73: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Auch im Visitor findet sich strukturierte Rekursion

data CarElement = Car [CarElement] | Wheel String | Body | Engine

visit :: (CarElement -> a) -> CarElement -> [a] visit f (Car es) = concat (map (visit f) es) ++ [f (Car es)] visit f x = [f x]

printCar car = visit toString car where toString Body = "Visit Body" toString Engine = "Visit Engine" toString Wheel s = "Visit Wheel " ++ s toString Car es = "Visit Car"

Separation of Concerns

Page 74: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Recursion is the goto of functional programming.

–Erik Meijer

Page 75: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Leichtgewichtige Threads

Erlang Prozesse sind nebenläufige, meist rekursive Funktionen

CalcProc = spawn(fun() -> calc_loop(0))

calc_loop(Acc) -> NewAcc = receive {mul, X} -> Acc * X; {add, X} -> Acc + X; clear -> 0; {get, Pid} -> Pid ! {result, Acc}, Acc; _IgnoredMsg -> Acc end, calc_loop(NewAcc).

Auswahl der Nachrichten durch Pattern Matching

Funktioniert dank Tail Call Optimization

Page 76: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Nebenläufige Endliche Automaten durch Prozesse, Funktionen und Messaging statt State-Pattern

Idle

Ringing Dial

Connected off_hook

on_hook

incoming off_hook

idle() -> receive {Number, incoming} -> start_ringing(), ringing(Number); off_hook -> start_tone(), dial() end. ringing(Number) -> receive {Number, off_hook} -> stop_ringing(), connected(Number); {Number, other_on_hook} -> stop_ringing(), idle() end.

other_ on_hook

Cesarini/Thompson: Erlang Programming 2009

Page 77: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Lazy Evaluation und unendliche Datenstrukturen

Lazy Evaluation:

(Teil-)Ausdrücke werden nur ausgewertet, wenn sie benötigt werden

head (x:xs) = x

Mit Lazy Evaluation gilt:

head [42.0, 1.0/0] == 42.0

Essentiell, um eigene Kontrollstrukturen zu definieren

unless cond x y = if !cond then x else y

Ideal für DSLs

Page 78: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Lazy Evaluation und unendliche Datenstrukturen

Mit Lazy Evaluation werden (potentiell) unendliche Datenstrukturen möglich

nats = [0 ..] take 5 nats == [0, 1, 2, 3, 4]

Wurzel-Berechnung nach Newton-Raphson:

sqrtSequence n = iterate (next n) n where next n x = (x + n/x)/2.0

sqrtSequence 2

>> [2.0, 1.5, 1.4166666666666665, 1.4142156862745097, 1.4142135623746899, 1.414213562373095, 1.414213562373095, 1.414213562373095, 1.414213562373095, …

iterate f n = [n,f(n),f2(n),f3(n), …]

http

://w

ww

.flic

kr.c

om/p

hoto

s/ro

bbie

73/

Page 79: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Pipes and Filters

Die Mächtigkeit der Unix-Shell kommt durch Pipes&Filters Konstruktionen cat *.txt | tr –sc A-Za-z '\n' | tr a-z A-Z | sort | uniq –c | sort –nr | head

Allgemein

prg1 –p1 <arg | prg2 –p2 | prg3 –p3 | prg4 –p4

Dies geht auch mit lazy Lists und Funktionskomposition

fct4 p4 . fct3 p3 . fct2 p2 . fct1 p1 $ arg

Idiomatisch in Haskell

Partial Application

Listen als Transfer-Container

Funktions- komposition

enspricht Pipe

Funktions- applikation enspricht <

Page 80: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Map/Reduce

Berechnung der (unabhängigen)

Zwischenergebnisse

Zusammenfassung

zum Endergebnis

Inspiration für s Map-Reduce-Framework (C++)

x1

x2

.

.

.

xn

f(x1)

f(x2)

.

.

.

f(xn)

map f reduce y = f(x1) … f(xn)

Page 81: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Was es sonst noch gibt

Eine Reihe weiterer Themen müssen wir auslassen

• Memoization

• Kombinatoren

• Monaden

• Macros

• Typeful Programming

• Continuations

• Co-Algebraische Konstruktionen

• …

Page 82: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Fazit

Page 83: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Funktionale Programmierung

Andersartiger Programmierstil

• Neue Abstraktionen und Kombinationsmöglichkeiten

• Andere Zerlegung von Problemen

• Andere Denkweisen und Idiome

Einfachere Strukturen machen das Leben leichter

• Keine (kaum) Seiteneffekte

• Pure Functions

• Testen und Parallelität werden sehr viel einfacher

Page 84: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

© Zühlke 2011

Auswirkungen auf Architektur

Vieles bleibt gleich

• Architekturtreiber sind weiterhin die Qualitätsattribute

• Patterns werden zur Kommunikation für die Entwickler benötigt

Kreativität und Augenmaß bleiben zwei wichtige Eigenschaften der Architekten

• Gutes Design

• Klare Verantwortlichkeiten

Page 85: Oop2011 jenseits von fakultät und_fibunacci_alfert_loechner

Recommended