Download - Funktionales Programmieren mit Clojure
![Page 1: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/1.jpg)
CHANGE YOUR MINDSETFunktionales Programmieren mit Clojure
chris_betzxing.to/betz
![Page 2: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/2.jpg)
Promotion in KI - und ca. 10 Jahre Erfahrung mit Common LISP
eCommerce/Finance mit SinnerSchrader - in Java
Security / Visual Analytics bei Plath
Mobile Entertainment bei HEROLABS - mit Clojure
About me
![Page 3: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/3.jpg)
Mobile Sports Entertainment„Beat the coach“, live während reale Fußballspiele laufen
iOS Client, Clojure Server, MongoDB Backend
Typische Aufgaben: Processing eines Streams von Fußball-Events, Fanout von Scoring an alle Nutzer
HERO11
![Page 4: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/4.jpg)
Warum Clojure?
Start „auf der grünen Wiese“: Freie Wahl der Sprache
Scala? oder Clojure? oder Go?
Zwei Entwickler „pro Clojure“ (beide mit LISP-Erfahrung), einer „pro Scala“
![Page 5: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/5.jpg)
Was machen andere damit?
Twitter: big data processing (war Backtype: Storm)
Flightcaster: realtime flight delay prediction
Runa: real-time targeted offers based on statistical models (e-Commerce)
Prismatic: personal news aggregation
![Page 6: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/6.jpg)
Was uns fasziniert...
![Page 7: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/7.jpg)
SIMPLICITY
![Page 8: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/8.jpg)
Reduktion aufs Wesentliche
Java:class HelloWorldApp { public static void main(String[] args) { System.out.println("Hello World!"); }}
Clojure:(println "Hello World!")
SIMPLICITY
![Page 9: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/9.jpg)
Erweitertes Beispiel,aus : Programming Clojure, Stuart Halloway
SIMPLICITY
![Page 10: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/10.jpg)
org.apache.commons.lang.StringUtils:
indexOfAny - findet in einem String das erste Vorkommen eines Zeichens aus einer vorgegebenen Menge
StringUtils.indexOfAny(null, *) = -1StringUtils.indexOfAny("", *) = -1StringUtils.indexOfAny(*, null) = -1StringUtils.indexOfAny(*, []) = -1StringUtils.indexOfAny("zzabyycdxx",['z','a']) = 0StringUtils.indexOfAny("zzabyycdxx",['b','y']) = 3StringUtils.indexOfAny("aba", ['z']) = -1
SIMPLICITY
![Page 11: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/11.jpg)
public static int indexOfAny(String str, char[] searchChars) { if (isEmpty(str) || ArrayUtils.isEmpty(searchChars)) { return -1; } for (int i = 0; i < str.length(); i++) { char ch = str.charAt(i); for (int j = 0; j < searchChars.length; j++) { if (searchChars[j] == ch) { return i; } return -1; } }}
SIMPLICITY
![Page 12: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/12.jpg)
Wie macht man das in Clojure?
SIMPLICITY
![Page 13: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/13.jpg)
(defn indexed [coll] (map vector (iterate inc 0) coll))
(indexed "abcde")⇒ ([0 \a] [1 \b] [2 \c] [3 \d] [4 \e])
SIMPLICITY
![Page 14: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/14.jpg)
(defn index-filter [pred coll] (when pred (for [[idx elt] (indexed coll) :when (pred elt)] idx)))
(index-filter #{\a \b} "abcdbbb")⇒ (0 1 4 5 6)
(index-filter #{\a \b} "xyz")⇒ ()
SIMPLICITY
![Page 15: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/15.jpg)
(defn index-of-any [pred coll] (first (index-filter pred coll)))
(index-of-any #{\z \a} "zzabyycdxx")⇒0
(index-of-any #{\b \y} "zzabyycdxx")⇒3
SIMPLICITY
![Page 16: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/16.jpg)
(defn indexed [coll] (map vector (iterate inc 0) coll))
(defn index-filter [pred coll] (when pred (for [[idx elt] (indexed coll) :when (pred elt)] idx)))
(defn index-of-any [pred coll] (first (index-filter pred coll)))
SIMPLICITY
![Page 17: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/17.jpg)
Simplicity
Metrik LOC Branches Exits/Method Variables
Java imperativ 14 4 3 3
Clojurefunktional 6 1 1 0
SIMPLICITY
![Page 18: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/18.jpg)
weitere Unterschiede
SIMPLICITY
![Page 19: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/19.jpg)
weitere Unterschiede
indexOfAny sucht nur in Strings, index-of-any durchsucht beliebige sequences
SIMPLICITY
![Page 20: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/20.jpg)
weitere Unterschiede
indexOfAny sucht nur in Strings, index-of-any durchsucht beliebige sequences
indexOfAny sucht nach einem Set von Characters, index-of-any kann beliebige Prädikate verwenden
SIMPLICITY
![Page 21: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/21.jpg)
weitere Unterschiede
indexOfAny sucht nur in Strings, index-of-any durchsucht beliebige sequences
indexOfAny sucht nach einem Set von Characters, index-of-any kann beliebige Prädikate verwenden
indexOfAny liefert den ersten Treffer, index-filter liefert alle Treffer und kann mit anderen Filtern kombiniert werden.
SIMPLICITY
![Page 22: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/22.jpg)
weitere Unterschiede
indexOfAny sucht nur in Strings, index-of-any durchsucht beliebige sequences
indexOfAny sucht nach einem Set von Characters, index-of-any kann beliebige Prädikate verwenden
indexOfAny liefert den ersten Treffer, index-filter liefert alle Treffer und kann mit anderen Filtern kombiniert werden.
find the third occurrence of “heads” in a series of coin flips:(nth (index-filter #{:h} [:t :t :h :t :h :t :t :t :h :h]) 2)⇒8
SIMPLICITY
![Page 23: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/23.jpg)
weitere Unterschiede
indexOfAny sucht nur in Strings, index-of-any durchsucht beliebige sequences
indexOfAny sucht nach einem Set von Characters, index-of-any kann beliebige Prädikate verwenden
indexOfAny liefert den ersten Treffer, index-filter liefert alle Treffer und kann mit anderen Filtern kombiniert werden.
find the third occurrence of “heads” in a series of coin flips:(nth (index-filter #{:h} [:t :t :h :t :h :t :t :t :h :h]) 2)⇒8
simpler, l
ess error
prone,
and more g
eneral
SIMPLICITY
![Page 24: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/24.jpg)
lazy sequences
Natürlich werden in index-of-any nicht erst alle Treffer erzeugt und dann alle bis auf den ersten weggeworfen!
Siehe auch infinite sequences...
SIMPLICITY
![Page 25: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/25.jpg)
for: Sequence comprehension
syntaktisches Konstrukt zum Erzeugen einer Liste aus existierenden Listen
entlehnt aus mathematischer „set notation“
S = {2*x | x ∈ℕ, x² > 3}
SIMPLICITY
![Page 26: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/26.jpg)
Unsere! Sprache
![Page 27: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/27.jpg)
Die Sprache ist vollständig erweiterbar.
Erweiterungen sind vom eigentlichen Sprachkern nicht zu unterscheiden.
UNSERE! Sprache
![Page 28: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/28.jpg)
Beispiel aus dem Noir Webframework:
(defpage „/person/:id.html“ [id]
...)
UNSERE! Sprache
![Page 29: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/29.jpg)
Beispiel aus Monger:
;; find scores 10 to 20(with-collection "scores" (find {}) (fields ,,, [:score :name]) (sort ,,, {:score -1}) (limit ,,, 10) (skip ,,, 10))
UNSERE! Sprache
![Page 30: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/30.jpg)
- Homoiconicity: Code is Data
- Das mächtigste Makrosystem:Clojure verwenden, um Clojure zu erzeugen
„The whole language there all the time.“ P. Graham
UNSERE! Sprache
Hintergrund der Erweiterbarkeit
![Page 31: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/31.jpg)
Java-Interop
![Page 32: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/32.jpg)
alle Java - Libraries stehen zur Verfügung
viele wichtige Libs mit clj-wrappern
interessante Libs in Clojure:noir (Web Framework), avout (noch sehr beta), congomongo bzw. monger (MongoDB)
Java-Interop
![Page 33: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/33.jpg)
Aber:
Man braucht ein anderes Mindset
![Page 34: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/34.jpg)
Funktional- was heisst
das?
![Page 35: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/35.jpg)
Funktionen als First-class Objekte
Maximum einer Collection von Zahlen?
Wie würde man das in Java machen?
Funktional
![Page 36: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/36.jpg)
Funktionen als First-class Objekte
Maximum einer Collection von Zahlen?
Wie würde man das in Java machen?
If, Hilfsvariable, Schleife, ...
Funktional
![Page 37: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/37.jpg)
(reduce max [35 62 -12 43 56 7])
Funktional
![Page 38: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/38.jpg)
Reducereduce
(reduce f coll)(reduce f val coll)
f should be a function of 2 arguments. If val is not supplied,returns the result of applying f to the first 2 items in coll, thenapplying f to that result and the 3rd item, etc. If coll contains noitems, f must accept no arguments as well, and reduce returns theresult of calling f with no arguments. If coll has only 1 item, itis returned and f is not called. If val is supplied, returns theresult of applying f to val and the first item in coll, thenapplying f to that result and the 2nd item, etc. If coll contains noitems, returns val and f is not called.
Funktional
![Page 39: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/39.jpg)
Sortieren
Sortieren einer Liste von Geboten nach :bid (invers) und :timestamp (ältestes zuerst)
(first (sort-by ( juxt (comp (partial * -1) :bid) :timestamp) [{:id "af1" :bid 1 :timestamp 1} {:id "ba3" :bid 12 :timestamp 3} {:id "cd7" :bid 12 :timestamp 2}]))
Und ja, normalerweise machen wir das auch in der Datenbank ;)
Funktional
![Page 40: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/40.jpg)
comp - Funktionskomposition
partial - partial function application (fixes arguments)
juxt - juxtaposition of functions („Nebeneinanderstellung“)
Funktional
![Page 41: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/41.jpg)
Fibonacci:
In Java...
Funktional
![Page 42: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/42.jpg)
In Clojure - trivial:
(defn fibonacci [a] (cond (> a 1) (+ (fibonacci (- a 2)) (fibonacci (- a 1))) (= a 1) 1 (= a 0) 0)
Funktional
![Page 43: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/43.jpg)
In Clojure - clojure style
(def fib-seq ((fn rfib [a b] (lazy-seq (cons a (rfib b (+ a b))))) 0 1))
(take 20 fib-seq)
Funktional
![Page 44: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/44.jpg)
Domänenmodell
![Page 45: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/45.jpg)
Map kann beliebige Elemente als Werte enthalten (dynamische Typisierung):
{:first-name „Christian“, :age 39, :married true}
Domänenmodell
![Page 46: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/46.jpg)
Maps werden o$ herangezogen, um domain-objects abzubilden.
Keine Klassen und Objekte, sondern generische Maps.
Später evtl. ersetzt durch records (die dann intern in Java-Klassen abgebildet werden).
Achtung: Lokalität! Wo erzeuge ich Objekte? (encapsulation, ...)
Domänenmodell
![Page 47: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/47.jpg)
Spring: Eine unserer Sorgen
Wir haben in Java-Projekten immer stark auf Spring gesetzt. Wie macht man das in Clojure?
Inversion of Control
Dependency Injection(um gegen Interface entwickeln zu können, nicht konkrete Klassen)
![Page 48: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/48.jpg)
Inversion of Control
Reusable code controls the execution of problem-specific code
Spring
![Page 49: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/49.jpg)
Inversion of Control
Aber das ist doch genau funktionales Programmieren...
;; Create a word frequency map out of a large string s.
;; `s` is a long string containing a lot of words :)(reduce #(assoc %1 %2 (inc (%1 %2 0))) {} (re-seq #"\w+" s))
; (This can also be done using the `frequencies` function.)
Spring
![Page 50: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/50.jpg)
Dependency Injection
Zentral(declare create-person)
Im „Nutzcode“
(create-person „Christian“ „Betz“ :age 39)
In der Definition
(defn create-person [first-name last-name ...] ...)
Spring
![Page 51: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/51.jpg)
Wo Licht ist …oder
Was Java-Entwickler vermissen
![Page 52: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/52.jpg)
Übersicht
Es gibt keine Klassendefinition, also nicht zwingend eine „Übersicht“ darüber, wie „Objekte“ aufgebaut sind.
Licht und SCHATTEN
![Page 53: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/53.jpg)
Statische Typisierung
Natürlich bietet ein statisches Typsystem auch Sicherheit - Typverletzungen erkennt schon der Compiler.
Licht und SCHATTEN
![Page 54: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/54.jpg)
Tooling
Die Tools sind noch nicht so ausgerei$ wie bei Java. Insbesondere Refactoring Tools vermissen wir manchmal.
Licht und SCHATTEN
![Page 55: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/55.jpg)
Unsere „Lösung“
- automatisierte Tests(braucht man auch in Java)
- Dokumentation
- Validierungsfunktionen(braucht man sowieso)
Licht und SCHATTEN
![Page 56: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/56.jpg)
Und wie entwickelt man?
![Page 57: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/57.jpg)
Test-driven development?
![Page 58: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/58.jpg)
REPL-driven development!
![Page 59: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/59.jpg)
REPL und TestsInteraktive Entwicklung von Funktionen in der REPL
Erhöht die Testbarkeit, weil man in der REPL ja nicht immer das gesamte System hochfahren möchte.
Wenn man mit einem ersten Dra# zufrieden ist, dann macht man Tests daraus, verfeinert diese und verbessert die Funktion.
Das Ergebnis ist eine Funktion und ein Satz von Unit-Tests
Mein Liebling in schwierigen Fällen: (debug-repl)
https://github.com/GeorgeJahad/debug-repl
![Page 60: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/60.jpg)
Das Clojure Ecosystem
Projektmanagement: lein (maven wie es sein sollte)
Entwicklungsumgebung: Emacs, IntelliJ, Eclipse
Testframework: midje
Web-Framework: Noir
Hosting: Erst Heroku, jetzt AWS, Automatisierung mit Jenkins, Pallet
![Page 61: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/61.jpg)
Hacks explained: apropos+
(ns dev.apropos)
(defn apropos+ "Given a regular expression or stringable thing, return a seq of all definitions in all currently-loaded namespaces that match the str-or-pattern." [str-or-pattern] (let [matches? (if (instance? java.util.regex.Pattern str-or-pattern) #(re-find str-or-pattern (str (key %))) #(.contains (str (key %)) (str str-or-pattern)))] (for [ns (all-ns) public (ns-publics ns) :when (matches? public)] (second public))))
;; (in-ns 'user);; (use 'dev.apropos);; (apropos+ "*warn")
![Page 62: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/62.jpg)
Hacks explained: apropos+
(ns dev.apropos)
(defn apropos+ "Given a regular expression or stringable thing, return a seq of all definitions in all currently-loaded namespaces that match the str-or-pattern." [str-or-pattern] (let [matches? (if (instance? java.util.regex.Pattern str-or-pattern) #(re-find str-or-pattern (str (key %))) #(.contains (str (key %)) (str str-or-pattern)))] (for [ns (all-ns) public (ns-publics ns) :when (matches? public)] (second public))))
;; (in-ns 'user);; (use 'dev.apropos);; (apropos+ "*warn")
![Page 63: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/63.jpg)
Hacks explained: apropos+
(ns dev.apropos)
(defn apropos+ "Given a regular expression or stringable thing, return a seq of all definitions in all currently-loaded namespaces that match the str-or-pattern." [str-or-pattern] (let [matches? (if (instance? java.util.regex.Pattern str-or-pattern) #(re-find str-or-pattern (str (key %))) #(.contains (str (key %)) (str str-or-pattern)))] (for [ns (all-ns) public (ns-publics ns) :when (matches? public)] (second public))))
;; (in-ns 'user);; (use 'dev.apropos);; (apropos+ "*warn")
![Page 64: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/64.jpg)
Hacks explained: apropos+
(ns dev.apropos)
(defn apropos+ "Given a regular expression or stringable thing, return a seq of all definitions in all currently-loaded namespaces that match the str-or-pattern." [str-or-pattern] (let [matches? (if (instance? java.util.regex.Pattern str-or-pattern) #(re-find str-or-pattern (str (key %))) #(.contains (str (key %)) (str str-or-pattern)))] (for [ns (all-ns) public (ns-publics ns) :when (matches? public)] (second public))))
;; (in-ns 'user);; (use 'dev.apropos);; (apropos+ "*warn")
![Page 65: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/65.jpg)
Hacks explained: apropos+
(ns dev.apropos)
(defn apropos+ "Given a regular expression or stringable thing, return a seq of all definitions in all currently-loaded namespaces that match the str-or-pattern." [str-or-pattern] (let [matches? (if (instance? java.util.regex.Pattern str-or-pattern) #(re-find str-or-pattern (str (key %))) #(.contains (str (key %)) (str str-or-pattern)))] (for [ns (all-ns) public (ns-publics ns) :when (matches? public)] (second public))))
;; (in-ns 'user);; (use 'dev.apropos);; (apropos+ "*warn")
![Page 66: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/66.jpg)
user=> (apropos+ "*warn")
(#'clojure.core/*warn-on-reflection*)
user=> (apropos+ "format")
(#'clojure.pprint/formatter-out #'clojure.pprint/formatter #'clojure.pprint/cl-format #'clojure.core/format)
![Page 67: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/67.jpg)
Recap
![Page 68: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/68.jpg)
Insgesamt: Super-zufrieden.
Aber: Es gab natürlich Probleme in der Adaption.
Änderung der Denke notwendig... Arbeit ohne "mal schnell eine Variable hochzählen" ist nicht immer einfach.
Weniger Code (d.h. weniger zu lesen und zu warten, was 90% der Arbeit ausmacht)
More fun - just dive into your program using the REPL
![Page 69: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/69.jpg)
Clojure-Dojo?
![Page 70: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/70.jpg)
lein (https://github.com/technomancy/leiningen)
~/.lein/profiles.clj:{:user {:plugins [[lein-midje "2.0.0-SNAPSHOT"][lein-noir "1.2.1"]]}}
noir (http://webnoir.org)
foundation: (http://foundation.zurb.com/)
Branch: http://branch.com/featured
-> lein new noir gwitter
http://localhost:8080/
![Page 71: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/71.jpg)
Mehr Infos...?
![Page 72: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/72.jpg)
Full Disclojure (Vimeo)http://vimeo.com/channels/fulldisclojure/videos
Clojure - Functional Programming for the JVMhttp://java.ociweb.com/mark/clojure/article.html
Clojure Docshttp://clojuredocs.org/
Closure/West Conference (Slides in github)http://clojurewest.org
@planetclojure, @fogus, @stuarthalloway, ...
![Page 73: Funktionales Programmieren mit Clojure](https://reader034.vdocuments.net/reader034/viewer/2022051817/54799c9fb4af9fc9158b4890/html5/thumbnails/73.jpg)
Danke !
Images:http://www.flickr.com/photos/marcp_dmoz/4138211812http://www.flickr.com/photos/b-natix/5249425587http://www.flickr.com/photos/stuckincustoms/4208255182http://www.flickr.com/photos/abbyladybug/491270355http://www.flickr.com/photos/petereed/496392956/http://www.flickr.com/photos/visualpanic/2394430691http://www.flickr.com/photos/bitzcelt/2762928930http://www.flickr.com/photos/tobstone/84696661http://www.flickr.com/photos/pulpolux/1306334352/http://www.flickr.com/photos/yashna13/5101434185/http://www.flickr.com/photos/go_freyer/3185104403http://www.flickr.com/photos/seier/4797164691/http://www.flickr.com/photos/visualpanic/2512530843http://www.flickr.com/photos/zeze57/5717675695