SlideShare ist ein Scribd-Unternehmen logo
Funktioniert’s?
Funktionale Programmierung für Anfänger
Funktional, das ist doch nur für Esoteriker?!
Funktional, das ist doch nur für Esoteriker?!
ABN AMRO Amsterdam Risikoanalysen Investmentbanking
AT&T Netzwerksicherheit: Verarbeitung von
Internet-Missbrauchsmeldungen
Bank of America Merril Lynch
Backend: Laden & Transformieren von Daten
Barclays Capital Quantitative Analytics Group
Mathematische Modellierung von Derivaten
Bluespec, Inc. Modellierung & Verifikation integrierter Schaltkreise
Credit Suisse Prüfen und Bearbeiten von Spreadsheets
Deutsche Bank Equity Proprietary Trading, Directional Credit
Trading Gesamte Software-Infrastruktur
Facebook Interne Tools
Factis Research, Freiburg Mobil-Lösungen (Backend)
fortytools gmbh Webbasierte Produktivitätstools - REST-Backend
Functor AB, Stockholm Statische Codeanalyse
Funktional, das ist doch nur für Esoteriker?!
Galois, Inc Security, Informationssicherheit, Kryptographie
Google Interne Projekte
IMVU, Inc. Social entertainment
JanRain Netzwerk- und Web-Software
MITRE Analyse kryptographischer Protokolle
New York Times Bildverarbeitung für die New York Fashion Week
NVIDIA In-House Tools
Parallel Scientific Hochskalierbares Cluster-Verwaltungssystem
Sankel Software CAD/CAM, Spiele, Computeranimation
Silk, Amsterdam Filtern und Visualisieren großer Datenmengen
Skedge Me Online-Terminvereinbarungen
Standard Chartered Bankensoftware
Starling Software, Tokio Automatisiertes Optionshandelssystem
Suite Solutions Verwaltung technischer Dokumentationen
(Quelle: http://www.haskell.org/haskellwiki/Haskell_in_industry)
Bekannte funktionale Sprachen
Lisp
Scheme
ML
OCamlMiranda
F#
Erlang
Clojure
Scala
Haskell
Bekannte funktionale Sprachen
Lisp
Scheme
ML
OCamlMiranda
F#
Erlang
Clojure
Scala
Haskell
(JavaScript)
(Java 8)
Bekannte funktionale Sprachen
Lisp
Scheme
ML
OCamlMiranda
F#
Erlang
Clojure
Scala
Haskell
(JavaScript)
(Java 8)
Was ist denn an funktionaler Programmierung so besonders?
Was ist denn an funktionaler Programmierung so besonders?
Immutability
Was ist denn an funktionaler Programmierung so besonders?
Immutability
Jeder Variablen darf nur einmal ein Wert zugewiesen werden
Was ist denn an funktionaler Programmierung so besonders?
Immutability
Jeder Variablen darf nur einmal ein Wert zugewiesen werden
In Java nicht direkt unterstützt
Was ist denn an funktionaler Programmierung so besonders?
Immutability
Jeder Variablen darf nur einmal ein Wert zugewiesen werden
In Java nicht direkt unterstützt
Kann trotzdem leicht verwirklicht werden:
class Point {
private final int x, y;
public Point (int x, int y) {
this.x = x;
this.y = y;
}
// only read x and y in the remaining code
}
Was ist denn an funktionaler Programmierung so besonders?
Seiteneffektfreiheit
Was ist denn an funktionaler Programmierung so besonders?
Seiteneffektfreiheit
„alles, was den Ablauf eines Computerprogramms oder die Außenwelt
verändert, ohne von einer Funktion berechnet worden zu sein“
Was ist denn an funktionaler Programmierung so besonders?
Seiteneffektfreiheit
„alles, was den Ablauf eines Computerprogramms oder die Außenwelt
verändert, ohne von einer Funktion berechnet worden zu sein“
Ein-/Ausgabe
Exceptions
Logging
Abhängigkeit von (externen) Konfigurationen
Veränderungen des Zustands
Nichtdeterminismus (z. B. Zufallszahlengenerator)
Was ist denn an funktionaler Programmierung so besonders?
Seiteneffektfreiheit
„alles, was den Ablauf eines Computerprogramms oder die Außenwelt
verändert, ohne von einer Funktion berechnet worden zu sein“
Ein-/Ausgabe
Exceptions
Logging
Abhängigkeit von (externen) Konfigurationen
Veränderungen des Zustands
Nichtdeterminismus (z. B. Zufallszahlengenerator)
Manche Sprachen zeigen das Vorhandensein von Seiteneffekten sogar
in der Typsignatur an
Was ist denn an funktionaler Programmierung so besonders?
Seiteneffektfreiheit
auch nicht direkt durch Java 8 unterstützt - Codierungsregeln helfen
Was ist denn an funktionaler Programmierung so besonders?
Seiteneffektfreiheit
auch nicht direkt durch Java 8 unterstützt - Codierungsregeln helfen
class SeparationOfSideEffects {
public void withSideEffect(){
String initialValue = System.console().readLine();
String result = withoutSideEffect(initialValue);
System.out.println("The Result: " + result);
}
public static String withoutSideEffect(String initialValue){
return /* function result */ ;
}
}
Was ist denn an funktionaler Programmierung so besonders?
Funktionen sind „first order citizens“
Was ist denn an funktionaler Programmierung so besonders?
Funktionen sind „first order citizens“
Mit Funktionen kann man dasselbe machen wie mit Strings oder Zahlen
Funktionen sind Werte
Funktionen sind Werte
Java 8: Statische Methoden
class Examples { static int staticTimes (int x, int y) { return x * y; } }
IntBinaryOperator timesVar = Examples::staticTimes;
timesVar.applyAsInt(3, 5); // 15
Funktionen sind Werte
Java 8: Objektmethoden
class Examples { int times (int x, int y) { return x * y; } }
Examples examples = new Examples();
IntBinaryOperator timesVar = examples::times;
timesVar.applyAsInt(3, 5); // 15
Funktionen sind Werte
Java 8: Lambdas
IntBinaryOperator times = (x, y) -> x * y;
times.applyAsInt(3, 5); // 15
Funktionen sind Werte
Java 8: Lambdas (mit eigenem Funktionsinterface)
interface TimesFunction { int eval(int x, int y); }
TimesFunction times = (x, y) -> x * y;
times.eval(3, 5); // 15
Funktionen sind Werte
Java 8: Lambdas (mit eigenem Funktionsinterface)
interface TimesFunction { int eval(int x, int y); }
TimesFunction times = (x, y) -> x * y;
times.eval(3, 5); // 15
Haskell:
times x y = x * y
timesVar = times
timesVar 3 5 -- 15
Funktionen sind Funktionsparameter
Funktionen sind Funktionsparameter
Java 8:
class Examples {
static int apply(IntUnaryOperator func, int arg) {
return func.applyAsInt(arg);
}
}
Examples.apply(x -> 3 * x, 5); // 15
Funktionen sind Funktionsparameter
Java 8:
class Examples {
static int apply(IntUnaryOperator func, int arg) {
return func.applyAsInt(arg);
}
}
Examples.apply(x -> 3 * x, 5); // 15
Haskell:
apply func arg = func arg
apply ( x -> 3 * x) 5 -- 15
Funktionen sind Rückgabewerte
Funktionen sind Rückgabewerte
Java 8:
interface FunctionFunction { IntUnaryOperator eval(int x); }
FunctionFunction times = x -> { return y -> x * y; };
times.eval(3).applyAsInt(5); // 15
Funktionen sind Rückgabewerte
Java 8:
interface FunctionFunction { IntUnaryOperator eval(int x); }
FunctionFunction times = x -> { return y -> x * y; };
times.eval(3).applyAsInt(5); // 15
Haskell:
times x = (y -> x * y)
times 3 5 -- 15
Komisch, oder?
Java 8: Zwei verschiedene Aufrufe
IntBinaryOperator times = (x, y) -> x * y;
times.applyAsInt(3, 5); // 15
FunctionFunction times = x -> { return y -> x * y; };
times.eval(3).applyAsInt(5); // 15
Haskell: Zweimal derselbe Aufruf
times x y = x * y
times 3 5 -- 15
times x = (y -> x * y)
times 3 5 -- 15
Currying! (oder auch Schönfinkeln)
Currying! (oder auch Schönfinkeln)
In manchen funktionalen Sprachen schreiben wir:
times x y = x * y
und eigentlich passiert Folgendes:
times x = (y -> x * y)
Currying! (oder auch Schönfinkeln)
In manchen funktionalen Sprachen schreiben wir:
times x y = x * y
und eigentlich passiert Folgendes:
times x = (y -> x * y)
Denn: Funktionen haben immer genau ein Argument
Currying! (oder auch Schönfinkeln)
In manchen funktionalen Sprachen schreiben wir:
times x y = x * y
und eigentlich passiert Folgendes:
times x = (y -> x * y)
Denn: Funktionen haben immer genau ein Argument
Nutzen: Partielle Evaluierung:
times x y = x * y
times3 = times 3
times3 5 -- 15
Wichtige Bibliotheksfunktionen: filter
filter oder auch select
Wichtige Bibliotheksfunktionen: filter
filter oder auch select
Nimmt eine Collection und eine Funktion
Liefert diejenigen Elemente der Collection, für die die Funktion true
ergibt
Wichtige Bibliotheksfunktionen: filter
filter oder auch select
Nimmt eine Collection und eine Funktion
Liefert diejenigen Elemente der Collection, für die die Funktion true
ergibt
Java 8:
Stream<Integer> filteredStream =
asList(1, 2, 3, 4).stream().filter(x -> x % 2 == 0);
filteredStream.toArray(); // new Integer[]{2, 4}
filteredStream.collect(Collectors.toList()); // Liste mit 2 und 4
Wichtige Bibliotheksfunktionen: filter
filter oder auch select
Nimmt eine Collection und eine Funktion
Liefert diejenigen Elemente der Collection, für die die Funktion true
ergibt
Java 8:
Stream<Integer> filteredStream =
asList(1, 2, 3, 4).stream().filter(x -> x % 2 == 0);
filteredStream.toArray(); // new Integer[]{2, 4}
filteredStream.collect(Collectors.toList()); // Liste mit 2 und 4
Haskell:
filter (x -> x `mod` 2 == 0) [1,2,3,4] -- [2,4]
Wichtige Bibliotheksfunktionen: map
map oder auch collect
Wichtige Bibliotheksfunktionen: map
map oder auch collect
Nimmt eine Collection und eine Funktion
Liefert eine Collection, in der die Funktion auf jedes Element der
ursprünglichen Collection angewandt wurde
Wichtige Bibliotheksfunktionen: map
map oder auch collect
Nimmt eine Collection und eine Funktion
Liefert eine Collection, in der die Funktion auf jedes Element der
ursprünglichen Collection angewandt wurde
Java 8:
Arrays.asList(1, 2, 3, 4).stream().map(x -> x + 5).toArray();
// new Integer[]{6, 7, 8, 9}
Wichtige Bibliotheksfunktionen: map
map oder auch collect
Nimmt eine Collection und eine Funktion
Liefert eine Collection, in der die Funktion auf jedes Element der
ursprünglichen Collection angewandt wurde
Java 8:
Arrays.asList(1, 2, 3, 4).stream().map(x -> x + 5).toArray();
// new Integer[]{6, 7, 8, 9}
Haskell:
map (x -> x + 5) [1,2,3,4] -- [6,7,8,9]
Wichtige Bibliotheksfunktionen: reduce
reduce oder auch foldl / foldr oder inject
Wichtige Bibliotheksfunktionen: reduce
reduce oder auch foldl / foldr oder inject
Nimmt eine Collection, eine Funktion und einen Startwert
Verbindet Startwert und erstes Element der Collection mit Hilfe der
Funktion
Verbindet das Ergebnis mit dem nächsten Element der Collection
Setzt dies für alle Elemente der Collection fort, bis nur noch ein
Element übrigbleibt
Wichtige Bibliotheksfunktionen: reduce
reduce oder auch foldl / foldr oder inject
Java 8:
Arrays.asList(2, 3, 4, 5).stream().reduce(1, (x, y) -> x*y); // 120
Wichtige Bibliotheksfunktionen: reduce
reduce oder auch foldl / foldr oder inject
Java 8:
Arrays.asList(2, 3, 4, 5).stream().reduce(1, (x, y) -> x*y); // 120
Haskell:
foldl (*) 1 [2,3,4,5] -- 120
Typinferenz
Haskell: starkes statisches Typsystem
Leichtgewichtige Verwendung dank Typinferenz
Herleitung des allgemeinst möglichen Typs
Typinferenz
Haskell: starkes statisches Typsystem
Leichtgewichtige Verwendung dank Typinferenz
Herleitung des allgemeinst möglichen Typs
Beispiel:
f x = x
Typinferenz
Haskell: starkes statisches Typsystem
Leichtgewichtige Verwendung dank Typinferenz
Herleitung des allgemeinst möglichen Typs
Beispiel:
f x = x
Typ:
f :: a -> a
a : Typvariable (vergleichbar mit Generics in Java o. ä.)
-> Funktionstyp (Argumenttyp steht links, Ergebnistyp steht rechts)
Typinferenz (2)
f x = x + 1
Typinferenz (2)
f x = x + 1
Typ:
f :: Num a => a -> a
Num a : Typklasse. Einschränkung der Typvariablen a auf numerische
Typen
Typinferenz (2)
f x = x + 1
Typ:
f :: Num a => a -> a
Num a : Typklasse. Einschränkung der Typvariablen a auf numerische
Typen
Empfehlung: Typsignatur stets annotieren! Zur Überprüfung der eigenen
Annahmen.
Eine einfache Berechnung
sum =
10
i=1
i2
Eine einfache Berechnung
sum =
10
i=1
i2
int sum = 0;
for(int i = 1; i <= 10; i++) {
sum = sum + i * i;
}
Exkurs: Clean Code
Single Responsibility Principle
Exkurs: Clean Code
Single Responsibility Principle
Wie viele Verantwortlichkeiten hat dieser Code?
int sum = 0;
for(int i = 1; i <= 10; i++) {
sum = sum + i * i;
}
Exkurs: Clean Code
Single Responsibility Principle
Wie viele Verantwortlichkeiten hat dieser Code?
int sum = 0;
for(int i = 1; i <= 10; i++) {
sum = sum + i * i;
}
Erzeugen der Zahlenfolge von 1 bis 10
Exkurs: Clean Code
Single Responsibility Principle
Wie viele Verantwortlichkeiten hat dieser Code?
int sum = 0;
for(int i = 1; i <= 10; i++) {
sum = sum + i * i;
}
Erzeugen der Zahlenfolge von 1 bis 10
Quadrieren einer Zahl
Exkurs: Clean Code
Single Responsibility Principle
Wie viele Verantwortlichkeiten hat dieser Code?
int sum = 0;
for(int i = 1; i <= 10; i++) {
sum = sum + i * i;
}
Erzeugen der Zahlenfolge von 1 bis 10
Quadrieren einer Zahl
Berechnen der Quadratzahl jeder Zahl in der Folge
Exkurs: Clean Code
Single Responsibility Principle
Wie viele Verantwortlichkeiten hat dieser Code?
int sum = 0;
for(int i = 1; i <= 10; i++) {
sum = sum + i * i;
}
Erzeugen der Zahlenfolge von 1 bis 10
Quadrieren einer Zahl
Berechnen der Quadratzahl jeder Zahl in der Folge
Addieren zweier Zahlen
Exkurs: Clean Code
Single Responsibility Principle
Wie viele Verantwortlichkeiten hat dieser Code?
int sum = 0;
for(int i = 1; i <= 10; i++) {
sum = sum + i * i;
}
Erzeugen der Zahlenfolge von 1 bis 10
Quadrieren einer Zahl
Berechnen der Quadratzahl jeder Zahl in der Folge
Addieren zweier Zahlen
Aufsummieren der Quadratzahlen
Trennen der Verantwortlichkeiten
Erzeugen der Zahlenfolge von 1 bis 10
Quadrieren einer Zahl
Berechnen der Quadratzahl jeder Zahl in der Folge
Addieren zweier Zahlen
Aufsummieren der Quadratzahlen
Trennen der Verantwortlichkeiten
Erzeugen der Zahlenfolge von 1 bis 10
IntStream sequence = IntStream.rangeClosed(1, 10);
Quadrieren einer Zahl
Berechnen der Quadratzahl jeder Zahl in der Folge
Addieren zweier Zahlen
Aufsummieren der Quadratzahlen
Trennen der Verantwortlichkeiten
Erzeugen der Zahlenfolge von 1 bis 10
IntStream sequence = IntStream.rangeClosed(1, 10);
Quadrieren einer Zahl
IntUnaryOperator square = x -> x*x;
Berechnen der Quadratzahl jeder Zahl in der Folge
Addieren zweier Zahlen
Aufsummieren der Quadratzahlen
Trennen der Verantwortlichkeiten
Erzeugen der Zahlenfolge von 1 bis 10
IntStream sequence = IntStream.rangeClosed(1, 10);
Quadrieren einer Zahl
IntUnaryOperator square = x -> x*x;
Berechnen der Quadratzahl jeder Zahl in der Folge
IntStream squaredSequence = sequence.map(square);
Addieren zweier Zahlen
Aufsummieren der Quadratzahlen
Trennen der Verantwortlichkeiten
Erzeugen der Zahlenfolge von 1 bis 10
IntStream sequence = IntStream.rangeClosed(1, 10);
Quadrieren einer Zahl
IntUnaryOperator square = x -> x*x;
Berechnen der Quadratzahl jeder Zahl in der Folge
IntStream squaredSequence = sequence.map(square);
Addieren zweier Zahlen
IntBinaryOperator add = (x,y) -> x+y;
Aufsummieren der Quadratzahlen
Trennen der Verantwortlichkeiten
Erzeugen der Zahlenfolge von 1 bis 10
IntStream sequence = IntStream.rangeClosed(1, 10);
Quadrieren einer Zahl
IntUnaryOperator square = x -> x*x;
Berechnen der Quadratzahl jeder Zahl in der Folge
IntStream squaredSequence = sequence.map(square);
Addieren zweier Zahlen
IntBinaryOperator add = (x,y) -> x+y;
Aufsummieren der Quadratzahlen
Integer sum = squaredSequence.reduce(0, add);
Zusammensetzen der Komponenten
Java 8:
IntStream.rangeClosed(1, 10).map(x -> x*x).reduce(0, (x,y) -> x+y); // 385
Zusammensetzen der Komponenten
Java 8:
IntStream.rangeClosed(1, 10).map(x -> x*x).reduce(0, (x,y) -> x+y); // 385
Haskell:
foldl (+) 0 (map (x -> x*x) [1..10]) -- 385
Zusammensetzen der Komponenten
Java 8:
IntStream.rangeClosed(1, 10).map(x -> x*x).reduce(0, (x,y) -> x+y); // 385
Haskell:
foldl (+) 0 (map (x -> x*x) [1..10]) -- 385
oder
(>.>) x f = f x
[1..10] >.> map (x -> x*x) >.> foldl (+) 0 -- 385
Uff!
OK, alle einmal tief durchatmen :-)
Pattern Matching
Fibonacci-Funktion „naiv“:
fib x = if x < 2 then x else fib (x-1) + fib (x-2)
Pattern Matching
Fibonacci-Funktion „naiv“:
fib x = if x < 2 then x else fib (x-1) + fib (x-2)
Fibonacci-Funktion mit Pattern Matching:
fib 0 = 0
fib 1 = 1
fib x = fib (x-1) + fib (x-2)
Algebraische Datentypen
Binärbaum:
data Tree =
Node Tree Tree
| Leaf Int
Algebraische Datentypen
Binärbaum:
data Tree =
Node Tree Tree
| Leaf Int
myTree = Node (Node (Leaf 4) (Node (Leaf 7) (Leaf 1))) (Leaf 3)
Algebraische Datentypen
Binärbaum:
data Tree =
Node Tree Tree
| Leaf Int
myTree = Node (Node (Leaf 4) (Node (Leaf 7) (Leaf 1))) (Leaf 3)
Summenfunktion:
Algebraische Datentypen
Binärbaum:
data Tree =
Node Tree Tree
| Leaf Int
myTree = Node (Node (Leaf 4) (Node (Leaf 7) (Leaf 1))) (Leaf 3)
Summenfunktion:
treeSum (Leaf x) = x
Algebraische Datentypen
Binärbaum:
data Tree =
Node Tree Tree
| Leaf Int
myTree = Node (Node (Leaf 4) (Node (Leaf 7) (Leaf 1))) (Leaf 3)
Summenfunktion:
treeSum (Leaf x) = x
treeSum (Node m n) = treeSum m + treeSum n
Algebraische Datentypen
Binärbaum:
data Tree =
Node Tree Tree
| Leaf Int
myTree = Node (Node (Leaf 4) (Node (Leaf 7) (Leaf 1))) (Leaf 3)
Summenfunktion:
treeSum (Leaf x) = x
treeSum (Node m n) = treeSum m + treeSum n
treeSum myTree -- 15
Fazit
Funktionale Programmierung ist verbreiteter als man denkt
Manches lässt sich in den nicht-funktionalen Alltag integrieren
Viele Sprachen bringen funktionale Aspekte oder Zusatzmodule mit
Fazit
Funktionale Programmierung ist verbreiteter als man denkt
Manches lässt sich in den nicht-funktionalen Alltag integrieren
Viele Sprachen bringen funktionale Aspekte oder Zusatzmodule mit
Referenz:
Haskell: http://www.haskell.org
Vielen Dank!
Code & Folien auf GitHub:
https://github.com
/NicoleRauch/FunctionalProgrammingForBeginners
Nicole Rauch
E-Mail info@nicole-rauch.de
Twitter @NicoleRauch
Web http://www.nicole-rauch.de
Artikel in der nächsten (?) Java Aktuell
Ganztägiger Workshop

Weitere ähnliche Inhalte

PDF
Mehr Dynamik Durch Skriptsprachen
PDF
AdvancedTdd
PPT
JdbcTemplate aus Spring
PDF
Volkskrankheit "Stiefmuetterliche Indizierung"
TXT
Do while
PPTX
Prototype 1.7
PDF
Ruby is Magic - Episode #7: Closures
PPTX
Funktionale Programmierung und mehr mit Scala
Mehr Dynamik Durch Skriptsprachen
AdvancedTdd
JdbcTemplate aus Spring
Volkskrankheit "Stiefmuetterliche Indizierung"
Do while
Prototype 1.7
Ruby is Magic - Episode #7: Closures
Funktionale Programmierung und mehr mit Scala

Was ist angesagt? (16)

PDF
Scalaz introduction for Java programmers
KEY
Ruby on Rails SS09 05
KEY
Ruby on Rails SS09 08
PDF
Perl 5 Quiz Chemnitz Edition
PPTX
BIT I WiSe 2014 | Basisinformationstechnologie I - 08: Programmiersprachen I
PDF
Funktionales Programmieren mit Clojure
PDF
Java Persistence 2.0
PDF
P6oo
PDF
Dev Day 2019: Mirko Zeibig – "Hallo " <> "Elixir"
PPTX
Scala und Lift
PDF
Perl 5.20: Feature, Kultur, Module, Werkzeuge
PDF
Scala - A Scalable Language
PPTX
Was geht mit Java 17?
PDF
Nigh Session Scala
ODP
Praesentation TYPO3Camp Berlin Speed mit Extbase
Scalaz introduction for Java programmers
Ruby on Rails SS09 05
Ruby on Rails SS09 08
Perl 5 Quiz Chemnitz Edition
BIT I WiSe 2014 | Basisinformationstechnologie I - 08: Programmiersprachen I
Funktionales Programmieren mit Clojure
Java Persistence 2.0
P6oo
Dev Day 2019: Mirko Zeibig – "Hallo " <> "Elixir"
Scala und Lift
Perl 5.20: Feature, Kultur, Module, Werkzeuge
Scala - A Scalable Language
Was geht mit Java 17?
Nigh Session Scala
Praesentation TYPO3Camp Berlin Speed mit Extbase
Anzeige

Ähnlich wie Einführung in die funktionale Programmierung (20)

PDF
DWX 2016 - Monitoring 2.0 - Monitoring 2.0: Alles im Lot?
PDF
Go - Googles Sprache für skalierbare Systeme
PDF
Funktionale Reaktive Programmierung mit Sodium
PDF
Karlsruher Entwicklertag 2016 - Monitoring 2.0: Alles im Lot?
PPT
Übersicht Skriptsprachen
PDF
.NET Summit 2016 München: EcmaScript 2015+ with TypeScript
PDF
Java Streams und Lambdas
PDF
Warum ECMAScript 6 die Welt ein Stückchen besser macht
PDF
Microbenchmarks - Wer nicht weiß, was er misst misst Mist
PPTX
TypeScript
PPS
2006 - NRW Conf: Asynchronous asp.net
ODP
jQuery & CouchDB - Die zukünftige Webentwicklung?
PDF
Skalierbare Anwendungen mit Google Go
ODP
PDF
Funktionale Programmierung mit Java - Andreas Jürgensen
PDF
Prometheus Monitoring
PDF
An Introduction to Ruby On Rails
PDF
Lehmanns Rails Erweitern
PDF
Modern angular 02_angular_mit_type_script
PDF
DWX 2016 - Monitoring 2.0 - Monitoring 2.0: Alles im Lot?
Go - Googles Sprache für skalierbare Systeme
Funktionale Reaktive Programmierung mit Sodium
Karlsruher Entwicklertag 2016 - Monitoring 2.0: Alles im Lot?
Übersicht Skriptsprachen
.NET Summit 2016 München: EcmaScript 2015+ with TypeScript
Java Streams und Lambdas
Warum ECMAScript 6 die Welt ein Stückchen besser macht
Microbenchmarks - Wer nicht weiß, was er misst misst Mist
TypeScript
2006 - NRW Conf: Asynchronous asp.net
jQuery & CouchDB - Die zukünftige Webentwicklung?
Skalierbare Anwendungen mit Google Go
Funktionale Programmierung mit Java - Andreas Jürgensen
Prometheus Monitoring
An Introduction to Ruby On Rails
Lehmanns Rails Erweitern
Modern angular 02_angular_mit_type_script
Anzeige

Mehr von Digicomp Academy AG (20)

PDF
Becoming Agile von Christian Botta – Personal Swiss Vortrag 2019
PDF
Swiss IPv6 Council – Case Study - Deployment von IPv6 in einer Container Plat...
PPTX
Innovation durch kollaboration gennex 2018
PDF
Roger basler meetup_digitale-geschaeftsmodelle-entwickeln_handout
PDF
Roger basler meetup_21082018_work-smarter-not-harder_handout
PDF
Xing expertendialog zu nudge unit x
PDF
Responsive Organisation auf Basis der Holacracy – nur ein Hype oder die Zukunft?
PDF
IPv6 Security Talk mit Joe Klein
PDF
Agiles Management - Wie geht das?
PPTX
Gewinnen Sie Menschen und Ziele - Referat von Andi Odermatt
PDF
Querdenken mit Kreativitätsmethoden – XING Expertendialog
PDF
Xing LearningZ: Digitale Geschäftsmodelle entwickeln
PDF
Swiss IPv6 Council: The Cisco-Journey to an IPv6-only Building
PDF
UX – Schlüssel zum Erfolg im Digital Business
PDF
Minenfeld IPv6
PDF
Was ist design thinking
PDF
Die IPv6 Journey der ETH Zürich
PDF
Zahlen Battle: klassische werbung vs.online-werbung-somexcloud
PDF
General data protection regulation-slides
PDF
Möglichkeiten der Online-Werbung - Referat von Matteo Schürch
Becoming Agile von Christian Botta – Personal Swiss Vortrag 2019
Swiss IPv6 Council – Case Study - Deployment von IPv6 in einer Container Plat...
Innovation durch kollaboration gennex 2018
Roger basler meetup_digitale-geschaeftsmodelle-entwickeln_handout
Roger basler meetup_21082018_work-smarter-not-harder_handout
Xing expertendialog zu nudge unit x
Responsive Organisation auf Basis der Holacracy – nur ein Hype oder die Zukunft?
IPv6 Security Talk mit Joe Klein
Agiles Management - Wie geht das?
Gewinnen Sie Menschen und Ziele - Referat von Andi Odermatt
Querdenken mit Kreativitätsmethoden – XING Expertendialog
Xing LearningZ: Digitale Geschäftsmodelle entwickeln
Swiss IPv6 Council: The Cisco-Journey to an IPv6-only Building
UX – Schlüssel zum Erfolg im Digital Business
Minenfeld IPv6
Was ist design thinking
Die IPv6 Journey der ETH Zürich
Zahlen Battle: klassische werbung vs.online-werbung-somexcloud
General data protection regulation-slides
Möglichkeiten der Online-Werbung - Referat von Matteo Schürch

Einführung in die funktionale Programmierung

  • 2. Funktional, das ist doch nur für Esoteriker?!
  • 3. Funktional, das ist doch nur für Esoteriker?! ABN AMRO Amsterdam Risikoanalysen Investmentbanking AT&T Netzwerksicherheit: Verarbeitung von Internet-Missbrauchsmeldungen Bank of America Merril Lynch Backend: Laden & Transformieren von Daten Barclays Capital Quantitative Analytics Group Mathematische Modellierung von Derivaten Bluespec, Inc. Modellierung & Verifikation integrierter Schaltkreise Credit Suisse Prüfen und Bearbeiten von Spreadsheets Deutsche Bank Equity Proprietary Trading, Directional Credit Trading Gesamte Software-Infrastruktur Facebook Interne Tools Factis Research, Freiburg Mobil-Lösungen (Backend) fortytools gmbh Webbasierte Produktivitätstools - REST-Backend Functor AB, Stockholm Statische Codeanalyse
  • 4. Funktional, das ist doch nur für Esoteriker?! Galois, Inc Security, Informationssicherheit, Kryptographie Google Interne Projekte IMVU, Inc. Social entertainment JanRain Netzwerk- und Web-Software MITRE Analyse kryptographischer Protokolle New York Times Bildverarbeitung für die New York Fashion Week NVIDIA In-House Tools Parallel Scientific Hochskalierbares Cluster-Verwaltungssystem Sankel Software CAD/CAM, Spiele, Computeranimation Silk, Amsterdam Filtern und Visualisieren großer Datenmengen Skedge Me Online-Terminvereinbarungen Standard Chartered Bankensoftware Starling Software, Tokio Automatisiertes Optionshandelssystem Suite Solutions Verwaltung technischer Dokumentationen (Quelle: http://www.haskell.org/haskellwiki/Haskell_in_industry)
  • 8. Was ist denn an funktionaler Programmierung so besonders?
  • 9. Was ist denn an funktionaler Programmierung so besonders? Immutability
  • 10. Was ist denn an funktionaler Programmierung so besonders? Immutability Jeder Variablen darf nur einmal ein Wert zugewiesen werden
  • 11. Was ist denn an funktionaler Programmierung so besonders? Immutability Jeder Variablen darf nur einmal ein Wert zugewiesen werden In Java nicht direkt unterstützt
  • 12. Was ist denn an funktionaler Programmierung so besonders? Immutability Jeder Variablen darf nur einmal ein Wert zugewiesen werden In Java nicht direkt unterstützt Kann trotzdem leicht verwirklicht werden: class Point { private final int x, y; public Point (int x, int y) { this.x = x; this.y = y; } // only read x and y in the remaining code }
  • 13. Was ist denn an funktionaler Programmierung so besonders? Seiteneffektfreiheit
  • 14. Was ist denn an funktionaler Programmierung so besonders? Seiteneffektfreiheit „alles, was den Ablauf eines Computerprogramms oder die Außenwelt verändert, ohne von einer Funktion berechnet worden zu sein“
  • 15. Was ist denn an funktionaler Programmierung so besonders? Seiteneffektfreiheit „alles, was den Ablauf eines Computerprogramms oder die Außenwelt verändert, ohne von einer Funktion berechnet worden zu sein“ Ein-/Ausgabe Exceptions Logging Abhängigkeit von (externen) Konfigurationen Veränderungen des Zustands Nichtdeterminismus (z. B. Zufallszahlengenerator)
  • 16. Was ist denn an funktionaler Programmierung so besonders? Seiteneffektfreiheit „alles, was den Ablauf eines Computerprogramms oder die Außenwelt verändert, ohne von einer Funktion berechnet worden zu sein“ Ein-/Ausgabe Exceptions Logging Abhängigkeit von (externen) Konfigurationen Veränderungen des Zustands Nichtdeterminismus (z. B. Zufallszahlengenerator) Manche Sprachen zeigen das Vorhandensein von Seiteneffekten sogar in der Typsignatur an
  • 17. Was ist denn an funktionaler Programmierung so besonders? Seiteneffektfreiheit auch nicht direkt durch Java 8 unterstützt - Codierungsregeln helfen
  • 18. Was ist denn an funktionaler Programmierung so besonders? Seiteneffektfreiheit auch nicht direkt durch Java 8 unterstützt - Codierungsregeln helfen class SeparationOfSideEffects { public void withSideEffect(){ String initialValue = System.console().readLine(); String result = withoutSideEffect(initialValue); System.out.println("The Result: " + result); } public static String withoutSideEffect(String initialValue){ return /* function result */ ; } }
  • 19. Was ist denn an funktionaler Programmierung so besonders? Funktionen sind „first order citizens“
  • 20. Was ist denn an funktionaler Programmierung so besonders? Funktionen sind „first order citizens“ Mit Funktionen kann man dasselbe machen wie mit Strings oder Zahlen
  • 22. Funktionen sind Werte Java 8: Statische Methoden class Examples { static int staticTimes (int x, int y) { return x * y; } } IntBinaryOperator timesVar = Examples::staticTimes; timesVar.applyAsInt(3, 5); // 15
  • 23. Funktionen sind Werte Java 8: Objektmethoden class Examples { int times (int x, int y) { return x * y; } } Examples examples = new Examples(); IntBinaryOperator timesVar = examples::times; timesVar.applyAsInt(3, 5); // 15
  • 24. Funktionen sind Werte Java 8: Lambdas IntBinaryOperator times = (x, y) -> x * y; times.applyAsInt(3, 5); // 15
  • 25. Funktionen sind Werte Java 8: Lambdas (mit eigenem Funktionsinterface) interface TimesFunction { int eval(int x, int y); } TimesFunction times = (x, y) -> x * y; times.eval(3, 5); // 15
  • 26. Funktionen sind Werte Java 8: Lambdas (mit eigenem Funktionsinterface) interface TimesFunction { int eval(int x, int y); } TimesFunction times = (x, y) -> x * y; times.eval(3, 5); // 15 Haskell: times x y = x * y timesVar = times timesVar 3 5 -- 15
  • 28. Funktionen sind Funktionsparameter Java 8: class Examples { static int apply(IntUnaryOperator func, int arg) { return func.applyAsInt(arg); } } Examples.apply(x -> 3 * x, 5); // 15
  • 29. Funktionen sind Funktionsparameter Java 8: class Examples { static int apply(IntUnaryOperator func, int arg) { return func.applyAsInt(arg); } } Examples.apply(x -> 3 * x, 5); // 15 Haskell: apply func arg = func arg apply ( x -> 3 * x) 5 -- 15
  • 31. Funktionen sind Rückgabewerte Java 8: interface FunctionFunction { IntUnaryOperator eval(int x); } FunctionFunction times = x -> { return y -> x * y; }; times.eval(3).applyAsInt(5); // 15
  • 32. Funktionen sind Rückgabewerte Java 8: interface FunctionFunction { IntUnaryOperator eval(int x); } FunctionFunction times = x -> { return y -> x * y; }; times.eval(3).applyAsInt(5); // 15 Haskell: times x = (y -> x * y) times 3 5 -- 15
  • 33. Komisch, oder? Java 8: Zwei verschiedene Aufrufe IntBinaryOperator times = (x, y) -> x * y; times.applyAsInt(3, 5); // 15 FunctionFunction times = x -> { return y -> x * y; }; times.eval(3).applyAsInt(5); // 15 Haskell: Zweimal derselbe Aufruf times x y = x * y times 3 5 -- 15 times x = (y -> x * y) times 3 5 -- 15
  • 34. Currying! (oder auch Schönfinkeln)
  • 35. Currying! (oder auch Schönfinkeln) In manchen funktionalen Sprachen schreiben wir: times x y = x * y und eigentlich passiert Folgendes: times x = (y -> x * y)
  • 36. Currying! (oder auch Schönfinkeln) In manchen funktionalen Sprachen schreiben wir: times x y = x * y und eigentlich passiert Folgendes: times x = (y -> x * y) Denn: Funktionen haben immer genau ein Argument
  • 37. Currying! (oder auch Schönfinkeln) In manchen funktionalen Sprachen schreiben wir: times x y = x * y und eigentlich passiert Folgendes: times x = (y -> x * y) Denn: Funktionen haben immer genau ein Argument Nutzen: Partielle Evaluierung: times x y = x * y times3 = times 3 times3 5 -- 15
  • 39. Wichtige Bibliotheksfunktionen: filter filter oder auch select Nimmt eine Collection und eine Funktion Liefert diejenigen Elemente der Collection, für die die Funktion true ergibt
  • 40. Wichtige Bibliotheksfunktionen: filter filter oder auch select Nimmt eine Collection und eine Funktion Liefert diejenigen Elemente der Collection, für die die Funktion true ergibt Java 8: Stream<Integer> filteredStream = asList(1, 2, 3, 4).stream().filter(x -> x % 2 == 0); filteredStream.toArray(); // new Integer[]{2, 4} filteredStream.collect(Collectors.toList()); // Liste mit 2 und 4
  • 41. Wichtige Bibliotheksfunktionen: filter filter oder auch select Nimmt eine Collection und eine Funktion Liefert diejenigen Elemente der Collection, für die die Funktion true ergibt Java 8: Stream<Integer> filteredStream = asList(1, 2, 3, 4).stream().filter(x -> x % 2 == 0); filteredStream.toArray(); // new Integer[]{2, 4} filteredStream.collect(Collectors.toList()); // Liste mit 2 und 4 Haskell: filter (x -> x `mod` 2 == 0) [1,2,3,4] -- [2,4]
  • 43. Wichtige Bibliotheksfunktionen: map map oder auch collect Nimmt eine Collection und eine Funktion Liefert eine Collection, in der die Funktion auf jedes Element der ursprünglichen Collection angewandt wurde
  • 44. Wichtige Bibliotheksfunktionen: map map oder auch collect Nimmt eine Collection und eine Funktion Liefert eine Collection, in der die Funktion auf jedes Element der ursprünglichen Collection angewandt wurde Java 8: Arrays.asList(1, 2, 3, 4).stream().map(x -> x + 5).toArray(); // new Integer[]{6, 7, 8, 9}
  • 45. Wichtige Bibliotheksfunktionen: map map oder auch collect Nimmt eine Collection und eine Funktion Liefert eine Collection, in der die Funktion auf jedes Element der ursprünglichen Collection angewandt wurde Java 8: Arrays.asList(1, 2, 3, 4).stream().map(x -> x + 5).toArray(); // new Integer[]{6, 7, 8, 9} Haskell: map (x -> x + 5) [1,2,3,4] -- [6,7,8,9]
  • 46. Wichtige Bibliotheksfunktionen: reduce reduce oder auch foldl / foldr oder inject
  • 47. Wichtige Bibliotheksfunktionen: reduce reduce oder auch foldl / foldr oder inject Nimmt eine Collection, eine Funktion und einen Startwert Verbindet Startwert und erstes Element der Collection mit Hilfe der Funktion Verbindet das Ergebnis mit dem nächsten Element der Collection Setzt dies für alle Elemente der Collection fort, bis nur noch ein Element übrigbleibt
  • 48. Wichtige Bibliotheksfunktionen: reduce reduce oder auch foldl / foldr oder inject Java 8: Arrays.asList(2, 3, 4, 5).stream().reduce(1, (x, y) -> x*y); // 120
  • 49. Wichtige Bibliotheksfunktionen: reduce reduce oder auch foldl / foldr oder inject Java 8: Arrays.asList(2, 3, 4, 5).stream().reduce(1, (x, y) -> x*y); // 120 Haskell: foldl (*) 1 [2,3,4,5] -- 120
  • 50. Typinferenz Haskell: starkes statisches Typsystem Leichtgewichtige Verwendung dank Typinferenz Herleitung des allgemeinst möglichen Typs
  • 51. Typinferenz Haskell: starkes statisches Typsystem Leichtgewichtige Verwendung dank Typinferenz Herleitung des allgemeinst möglichen Typs Beispiel: f x = x
  • 52. Typinferenz Haskell: starkes statisches Typsystem Leichtgewichtige Verwendung dank Typinferenz Herleitung des allgemeinst möglichen Typs Beispiel: f x = x Typ: f :: a -> a a : Typvariable (vergleichbar mit Generics in Java o. ä.) -> Funktionstyp (Argumenttyp steht links, Ergebnistyp steht rechts)
  • 54. Typinferenz (2) f x = x + 1 Typ: f :: Num a => a -> a Num a : Typklasse. Einschränkung der Typvariablen a auf numerische Typen
  • 55. Typinferenz (2) f x = x + 1 Typ: f :: Num a => a -> a Num a : Typklasse. Einschränkung der Typvariablen a auf numerische Typen Empfehlung: Typsignatur stets annotieren! Zur Überprüfung der eigenen Annahmen.
  • 57. Eine einfache Berechnung sum = 10 i=1 i2 int sum = 0; for(int i = 1; i <= 10; i++) { sum = sum + i * i; }
  • 58. Exkurs: Clean Code Single Responsibility Principle
  • 59. Exkurs: Clean Code Single Responsibility Principle Wie viele Verantwortlichkeiten hat dieser Code? int sum = 0; for(int i = 1; i <= 10; i++) { sum = sum + i * i; }
  • 60. Exkurs: Clean Code Single Responsibility Principle Wie viele Verantwortlichkeiten hat dieser Code? int sum = 0; for(int i = 1; i <= 10; i++) { sum = sum + i * i; } Erzeugen der Zahlenfolge von 1 bis 10
  • 61. Exkurs: Clean Code Single Responsibility Principle Wie viele Verantwortlichkeiten hat dieser Code? int sum = 0; for(int i = 1; i <= 10; i++) { sum = sum + i * i; } Erzeugen der Zahlenfolge von 1 bis 10 Quadrieren einer Zahl
  • 62. Exkurs: Clean Code Single Responsibility Principle Wie viele Verantwortlichkeiten hat dieser Code? int sum = 0; for(int i = 1; i <= 10; i++) { sum = sum + i * i; } Erzeugen der Zahlenfolge von 1 bis 10 Quadrieren einer Zahl Berechnen der Quadratzahl jeder Zahl in der Folge
  • 63. Exkurs: Clean Code Single Responsibility Principle Wie viele Verantwortlichkeiten hat dieser Code? int sum = 0; for(int i = 1; i <= 10; i++) { sum = sum + i * i; } Erzeugen der Zahlenfolge von 1 bis 10 Quadrieren einer Zahl Berechnen der Quadratzahl jeder Zahl in der Folge Addieren zweier Zahlen
  • 64. Exkurs: Clean Code Single Responsibility Principle Wie viele Verantwortlichkeiten hat dieser Code? int sum = 0; for(int i = 1; i <= 10; i++) { sum = sum + i * i; } Erzeugen der Zahlenfolge von 1 bis 10 Quadrieren einer Zahl Berechnen der Quadratzahl jeder Zahl in der Folge Addieren zweier Zahlen Aufsummieren der Quadratzahlen
  • 65. Trennen der Verantwortlichkeiten Erzeugen der Zahlenfolge von 1 bis 10 Quadrieren einer Zahl Berechnen der Quadratzahl jeder Zahl in der Folge Addieren zweier Zahlen Aufsummieren der Quadratzahlen
  • 66. Trennen der Verantwortlichkeiten Erzeugen der Zahlenfolge von 1 bis 10 IntStream sequence = IntStream.rangeClosed(1, 10); Quadrieren einer Zahl Berechnen der Quadratzahl jeder Zahl in der Folge Addieren zweier Zahlen Aufsummieren der Quadratzahlen
  • 67. Trennen der Verantwortlichkeiten Erzeugen der Zahlenfolge von 1 bis 10 IntStream sequence = IntStream.rangeClosed(1, 10); Quadrieren einer Zahl IntUnaryOperator square = x -> x*x; Berechnen der Quadratzahl jeder Zahl in der Folge Addieren zweier Zahlen Aufsummieren der Quadratzahlen
  • 68. Trennen der Verantwortlichkeiten Erzeugen der Zahlenfolge von 1 bis 10 IntStream sequence = IntStream.rangeClosed(1, 10); Quadrieren einer Zahl IntUnaryOperator square = x -> x*x; Berechnen der Quadratzahl jeder Zahl in der Folge IntStream squaredSequence = sequence.map(square); Addieren zweier Zahlen Aufsummieren der Quadratzahlen
  • 69. Trennen der Verantwortlichkeiten Erzeugen der Zahlenfolge von 1 bis 10 IntStream sequence = IntStream.rangeClosed(1, 10); Quadrieren einer Zahl IntUnaryOperator square = x -> x*x; Berechnen der Quadratzahl jeder Zahl in der Folge IntStream squaredSequence = sequence.map(square); Addieren zweier Zahlen IntBinaryOperator add = (x,y) -> x+y; Aufsummieren der Quadratzahlen
  • 70. Trennen der Verantwortlichkeiten Erzeugen der Zahlenfolge von 1 bis 10 IntStream sequence = IntStream.rangeClosed(1, 10); Quadrieren einer Zahl IntUnaryOperator square = x -> x*x; Berechnen der Quadratzahl jeder Zahl in der Folge IntStream squaredSequence = sequence.map(square); Addieren zweier Zahlen IntBinaryOperator add = (x,y) -> x+y; Aufsummieren der Quadratzahlen Integer sum = squaredSequence.reduce(0, add);
  • 71. Zusammensetzen der Komponenten Java 8: IntStream.rangeClosed(1, 10).map(x -> x*x).reduce(0, (x,y) -> x+y); // 385
  • 72. Zusammensetzen der Komponenten Java 8: IntStream.rangeClosed(1, 10).map(x -> x*x).reduce(0, (x,y) -> x+y); // 385 Haskell: foldl (+) 0 (map (x -> x*x) [1..10]) -- 385
  • 73. Zusammensetzen der Komponenten Java 8: IntStream.rangeClosed(1, 10).map(x -> x*x).reduce(0, (x,y) -> x+y); // 385 Haskell: foldl (+) 0 (map (x -> x*x) [1..10]) -- 385 oder (>.>) x f = f x [1..10] >.> map (x -> x*x) >.> foldl (+) 0 -- 385
  • 74. Uff! OK, alle einmal tief durchatmen :-)
  • 75. Pattern Matching Fibonacci-Funktion „naiv“: fib x = if x < 2 then x else fib (x-1) + fib (x-2)
  • 76. Pattern Matching Fibonacci-Funktion „naiv“: fib x = if x < 2 then x else fib (x-1) + fib (x-2) Fibonacci-Funktion mit Pattern Matching: fib 0 = 0 fib 1 = 1 fib x = fib (x-1) + fib (x-2)
  • 77. Algebraische Datentypen Binärbaum: data Tree = Node Tree Tree | Leaf Int
  • 78. Algebraische Datentypen Binärbaum: data Tree = Node Tree Tree | Leaf Int myTree = Node (Node (Leaf 4) (Node (Leaf 7) (Leaf 1))) (Leaf 3)
  • 79. Algebraische Datentypen Binärbaum: data Tree = Node Tree Tree | Leaf Int myTree = Node (Node (Leaf 4) (Node (Leaf 7) (Leaf 1))) (Leaf 3) Summenfunktion:
  • 80. Algebraische Datentypen Binärbaum: data Tree = Node Tree Tree | Leaf Int myTree = Node (Node (Leaf 4) (Node (Leaf 7) (Leaf 1))) (Leaf 3) Summenfunktion: treeSum (Leaf x) = x
  • 81. Algebraische Datentypen Binärbaum: data Tree = Node Tree Tree | Leaf Int myTree = Node (Node (Leaf 4) (Node (Leaf 7) (Leaf 1))) (Leaf 3) Summenfunktion: treeSum (Leaf x) = x treeSum (Node m n) = treeSum m + treeSum n
  • 82. Algebraische Datentypen Binärbaum: data Tree = Node Tree Tree | Leaf Int myTree = Node (Node (Leaf 4) (Node (Leaf 7) (Leaf 1))) (Leaf 3) Summenfunktion: treeSum (Leaf x) = x treeSum (Node m n) = treeSum m + treeSum n treeSum myTree -- 15
  • 83. Fazit Funktionale Programmierung ist verbreiteter als man denkt Manches lässt sich in den nicht-funktionalen Alltag integrieren Viele Sprachen bringen funktionale Aspekte oder Zusatzmodule mit
  • 84. Fazit Funktionale Programmierung ist verbreiteter als man denkt Manches lässt sich in den nicht-funktionalen Alltag integrieren Viele Sprachen bringen funktionale Aspekte oder Zusatzmodule mit Referenz: Haskell: http://www.haskell.org
  • 85. Vielen Dank! Code & Folien auf GitHub: https://github.com /NicoleRauch/FunctionalProgrammingForBeginners Nicole Rauch E-Mail info@nicole-rauch.de Twitter @NicoleRauch Web http://www.nicole-rauch.de Artikel in der nächsten (?) Java Aktuell Ganztägiger Workshop