FUNCTIONAL PROGRAMMING Real Life Functional Programming
Sascha Koch JUG Bielefeld 19.11.2014
Agenda • Einführung in die funktionale Programmierung • Reine FP in der JVM an Hand von Clojure
• Semi / Practical FP an Hand von Guava • Closures in Java 8 • Ausblick
λ
x
λx.T
S T
(λx.R)T
(λx.x b x a) pi
pi b pi a β-‐Reduktion
λx.x λx.a λf x.f (f x)
(λx y.x + y) 1 2 (((λx y.x + y) 1) 2) ((λy.1 + y) 2) λy.1 + y
λ x y.x λ x y.y A B C
λ z s.z λ n s.n s � s
λ n m s.n s � m s
Unterschiede zu imperativen Sprachen Funktionale Sprachen Imperative Sprachen
Building Blocks Funktionen Instruktionen
Zustand unveränderlich wird modifiziert
Variablen An Ausdruck gebunden Speicheradresse
Programmablauf Ausdrücke werden ausgewertet
Führt eine Menge von Instruktionen aus
Zusammenfassung • Lambda Kalkül • Formales System zur Definition von Funktionen • Turing-‐vollständig • Wie die Turing-‐Maschine nur ein abstraktes Modell • Grundlage für funktionale Programmiersprachen
• Alles sind Funktionen • Kombinatoren sind Lambda-‐Ausdrücke ohne freie Variablen • Lambda-‐Kalkül + Typisierung + syntaktischer Zucker à FP
Agenda • Einführung in die funktionale Programmierung ✔ • (Reine) FP in der JVM an Hand von Clojure
• Semi / Practical FP an Hand von Guava • Closures in Java 8 • Ausblick
Design by Tom Hickey and Rich Hickey
increment 1 ) (
Installation 1. Aktuelles clojure.jar laden (http://clojure.org/downloads) 2. Clone und build von GitHub
$ git clone https://github.com/clojure/clojure $ mvn clean install
• Clojure Programm starten: $ java –jar clojure-‐x.y.z.jar file.clj
• REPL starten: $ rlwrap java –jar clojure-‐x.y.z.jar
Installation • Installiere aktuelles Leiningen (http://leiningen.org)
$ lein repl $ lein new project $ lein test $ lein run $ lein jar $ lein uberjar $ lein deploy clojars (benötigt clojars.org account) http://www.classicshorts.com/stories/lvta.html
Atomic Data Types • Arbitrary precision integers 12345678987654 • Double 1.234 • BigDecimals 1.234M • Ratios 22/7 • Strings “fred“ „ethel“ • Character \a \b • Symbols fred ethel • Keywords :fred :ethel • Null nil • Booleans true false • Regex patterns #“a*b“
Datenstrukturen • Liste – einzeln verkettet, wachsen von vorne • (1 2 3 4 5), (fred ethel lucy), (list 1 2 3)
• Vectoren – Zugriff via Index, wachsen nach hinten • [1 2 3 4 5], [fred ethel lucy]
• Maps (key-‐value Paare) • {:a 1, :b 2, :c 3}, {1 „ethel“ 2 „fred“}
• Sets • #{fred ethel lucy}
• Everything nests
Syntax • Clojure ist homoikonisch • Datenstrukturen sind der Code • Keine weitere text-‐basierte Syntax • Syntax ist die Interpretation der Datenstruktur
Ausdrücke und Operationen • Alles ist ein Ausdruck expression • Die Datenliterale repräsentieren sich selbst • Außer bei Listen und Symbolen (dann passiert etwas) • Symbole – Binding zu einem Wert gesucht (lokal let, global def) • Liste – führt eine bestimmte Operation aus (op)
• (op ...) • op kann folgendes sein: • Spezielle Op (siehe clojure.lang.Compiler.java) à MAGIE • Makro • Funktion (Ausdruck welcher eine Funktion ergibt)
Funktionen • First class values (def five 5) (def sqr (fn [x] (* x x))) (sqr five) 25
• Makro defn (defn sqr „This method calculates the square root of n“ [x] (* x x))
Makros • defmacro
• macroexpand
• Beispiel „first“ oder „ifnot“ • (defn ff [a b] a) (defmacro mf [a b] a)
• (defn fifnot [i t e] (if (not i) t e)) (defmacro mifnot [i t e] `(if (not ~i) ~t ~e))
• Weitere Informationen: http://clojure.org/macros
Sequences • (seq coll) • (first seq) • (rest seq) • Sequences: list, vector, files, ...
Finally Functions • Hello world equivalent: factorial
• Several versions 1. Simple approach 2. Extended multiplication operator: *‘ 3. Loop-‐Recur-‐Pattern 4. reduce
Live Demo
Ring Demo
Java in Clojure • Sehr einfach: (def cal (java.util.Calendar/getInstance)) #‘user/cal (.getTimeInMillis cal) 1415399321833 (System/currentTimeMillis) 1415703691973
Clojure in Java • Generate classes for Java (ns de.coruco.binomial (:gen-‐class)) (defn binomial ...)
Clojure in Java • As of Clojure 1.6.0: import clojure.java.api.Clojure; import clojure.lang.Ifn; ... Ifn require = Clojure.var( „clojure.core“, „require“ ); require.invoke( Clojure.read( „de.coruco.binomial“ ) ); Ifn binomi = Clojure.var( „de.coruco.binomial“, „binomial“ ); Object result = binomi.invoke( 7, 6 );
Sechs Regeln der Clojure Programmierung
1. Vermeide direkte Rekursion 2. Benutze recur um Skalare oder kurze Sequenzen zu
verarbeiten 3. Verwende lazy Sequenzen um lange Sequenzen zu
verarbeiten 4. Erzeuge nicht unnötige Teile einer lazy Sequenz 5. Lernen Du musst die Funktionen von Sequenzen 6. Zerteile selbst einfache Probleme in triviale Probleme und
Du wirst eine Lösung in der Standard-‐Bibliothek finden (Teile und Herrsche)
Noch mehr? • midje
• Clojurescript
• :clojureD
• github
Agenda • Einführung in die funktionale Programmierung ✔ • Reine FP in der JVM an Hand von Clojure ✔
• Semi / Practical FP an Hand von Guava • Closures in Java 8 • Ausblick