You are on page 1of 120

Gernot Starke & Stefan Tilkow | innoQ

Erlang, Clojure & Co.: Was der Mainstream von Alternativen lernen kann

Erlang & Clojure


fr den Mainstream lernen knnen

Was Sie aus Prolog,

Gernot Starke, Stefan Tilkov

Thursday, April 19, 12

Wir ber uns...


Stefan Tilkov Gernot Starke

http://www.innoq.com

Thursday, April 19, 12

Prolog Clojure Erlang

Node.js

Thursday, April 19, 12

Prolog Clojure Erlang Kernkonzepte

Node.js

Thursday, April 19, 12

Prolog Clojure Erlang Kernkonzepte Praxistauglichkeit

Node.js

Thursday, April 19, 12

Prolog Clojure Erlang Kernkonzepte Praxistauglichkeit Java-Bibliotheken

Node.js

Thursday, April 19, 12

Prolog Clojure Erlang Kernkonzepte Praxistauglichkeit Java-Bibliotheken Java-Idiome

Node.js

Thursday, April 19, 12

Prolog

Thursday, April 19, 12

Anforderungen...
Hinweise:

1. Es gibt fnf Huser mit je einer anderen Farbe. 2. In jedem Haus wohnt eine Person anderer Nationalitt. 3. Jeder Hausbewohner bevorzugt ein bestimmtes Getrnk, raucht eine bestimmte Zigarettenmarke und hlt ein bestimmtes Haustier. 4. Keine der fnf Personen trinkt das gleiche Getrnk, raucht die gleichen Zigaretten oder hlt das gleiche Tier wie seine Nachbarn. Frage: Wem gehrt der Fisch?

Der Brite lebt im roten Haus. Der Schwede hlt einen Hund. Der Dne trinkt gern Tee. Das grne Haus steht direkt links neben dem weien Haus. Der Besitzer des grnen Hauses trinkt Kaffee. Die Person, die Pall Mall raucht, hlt einen Vogel. Der Mann, der im mittleren Haus wohnt, trinkt Milch. Der Besitzer des gelben Hauses raucht Dunhill. Der Norweger wohnt im ersten Haus. Der Marlboro-Raucher wohnt neben dem, der eine Katze hlt. Der Mann, der ein Pferd hlt, wohnt neben dem, der Dunhill raucht. Der Winfield-Raucher trinkt gern Bier. Der Norweger wohnt neben dem blauen Haus. Der Deutsche raucht Rothmans. Der Marlboro-Raucher hat einen Nachbarn, der Wasser trinkt.

Angeblich nach Einstein, hier aus Wikipedia

Thursday, April 19, 12

Lsung in Prolog
run :X =[_,_,_,_,_],/* Es gibt (nebeneinander) 5 Huser */ member([rot,brite,_,_,_],X),/* Der Brite lebt im roten Haus */ member([_,schwede,_,_,hund],X),/* Der Schwede hlt einen Hund */ member([_,daene,tee,_,_],X),/* Der Dne trinkt gern Tee */ links([gruen,_,_,_,_],[weiss,_,_,_,_],X),/* Das grne Haus steht links vom weien Haus */ member([gruen,_,kaffee,_,_],X),/* Der Besitzer des grnen Hauses trinkt Kaffee */ member([_,_,_,pallmall,vogel],X),/* Die Person, die Pall Mall raucht, hlt einen Vogel */ mittleres([_,_,milch,_,_],X),/* Der Mann, der im mittleren Haus wohnt, trinkt Milch */ member([gelb,_,_,dunhill,_],X),/* Der Besitzer des gelben Hauses raucht Dunhill */ erstes([_,norweger,_,_,_],X),/* Der Norweger wohnt im 1. Haus */ neben([_,_,_,marlboro,_],[_,_,_,_,katze],X),/* Der Marlboro-Raucher wohnt neben Katzenbesitzer */ neben([_,_,_,_,pferd],[_,_,_,dunhill,_],X),/* Der Pferdehalter wohnt neben dem Dunhillraucher */ member([_,_,bier,winfield,_],X),/* Der Winfield-Raucher trinkt gern Bier */ neben([_,norweger,_,_,_],[blau,_,_,_,_],X),/* Der Norweger wohnt neben dem blauen Haus */ member([_,deutsche,_,rothmans,_],X),/* Der Deutsche raucht Rothmans */ neben([_,_,_,marlboro,_],[_,_,wasser,_,_],X),/* Der Nachbar des Marlboro-Rauchers trinkt Wasser */ member([_,N,_,_,fisch],X),/* Der mit der Nationalitt N hat einen Fisch */ write(X),nl,/* Ausgabe aller Huser */ write('Der '),write(N),write(' hat einen Fisch als Haustier.'),nl.

Thursday, April 19, 12

Lsung in Prolog

run :X =[_,_,_,_,_],/* Es gibt (nebeneinander) 5 Huser */ member([rot,brite,_,_,_],X), /* Der Brite lebt im roten Haus */ member([_,schwede,_,_,hund],X), /* Der Schwede hlt einen Hund */ member([_,daene,tee,_,_],X), /* Der Dne trinkt gern Tee */ links([gruen,_,_,_,_],[weiss,_,_,_,_],X), /* Das grne Haus steht links vom weien Haus */
%.....

Thursday, April 19, 12

Lsung in Prolog

erstes(E,[E|_]). mittleres(M,[_,_,M,_,_]). links(A,B,[A,B|_]). links(A,B,[_|R]):- links(A,B,R). neben(A,B,L):- links(A,B,L);links(B,A,L).

Thursday, April 19, 12

Prolog
Basis: Unifikation von Termen
(Mustererkennung)

Vorgabe von Fakten und Regeln (mit freien Variablen) Prolog versucht, Wahrheit zu beweisen Beispiel: neben(A, b, [a,c,b,d]) -> A=c A=d

Thursday, April 19, 12

Prolog...

Backtracking = systematisches Ausprobieren

Thursday, April 19, 12

Prolog: Kernkonzepte
Regelorientierung Backtracking Deklarativer Ansatz

Thursday, April 19, 12

Prolog: Praxistauglichkeit
Schwierig (riskant): Integration in JavaMainstream tu-Prolog als Eclipse-Plugin, experimentell + fragil Gut geeignet fr Planungsprobleme

Thursday, April 19, 12

Prolog: Java-Bibliotheken
Regelsysteme heute geschfts- und integrationsfhig: kommerzielle Regel-Engines freie Regel-Engine(s), etwa JBoss-Drools

Thursday, April 19, 12

JBoss Drools

Thursday, April 19, 12

http://upload.wikimedia.org/wikipedia/en/1/1

Clojure

Thursday, April 19, 12

Clojure: Datenstrukturen

Thursday, April 19, 12

Clojure: Datenstrukturen
Numbers Strings Characters Keywords Symbols Regexps Lists Vectors Maps Sets
2 3 4 0.234 3/5 -2398989892820093093090292321 "Hello" "World" \a \b \c :first :last a b c #"Ch.*se" (a b c) ((:first :last "Str" 3) (a b)) [2 4 6 9 23] [2 4 6 [8 9] [10 11] 9 23] {:de "Deutschland", :fr "France"} #{"Bread" "Cheese" "Wine"}

Thursday, April 19, 12

Clojure: Datenstrukturen
Numbers Strings Characters Keywords Symbols Regexps Lists Vectors Maps Sets
2 3 4 0.234 3/5 -2398989892820093093090292321 "Hello" "World" \a \b \c :first :last a b c #"Ch.*se" (a b c) ((:first :last "Str" 3) (a b)) [2 4 6 9 23] [2 4 6 [8 9] [10 11] 9 23] {:de "Deutschland", :fr "France"} #{"Bread" "Cheese" "Wine"}

Thursday, April 19, 12

Clojure: Datenstrukturen
Numbers Strings Characters Keywords Symbols Regexps Lists Vectors Maps Sets
2 3 4 0.234 3/5 -2398989892820093093090292321 "Hello" "World" \a \b \c :first :last a b c #"Ch.*se" (a b c) ((:first :last "Str" 3) (a b)) [2 4 6 9 23] [2 4 6 [8 9] [10 11] 9 23] {:de "Deutschland", :fr "France"} #{"Bread" "Cheese" "Wine"}

Thursday, April 19, 12

Clojure: Datenstrukturen
Numbers Strings Characters Keywords Symbols Regexps Lists Vectors Maps Sets
2 3 4 0.234 3/5 -2398989892820093093090292321 "Hello" "World" \a \b \c :first :last a b c #"Ch.*se" (a b c) ((:first :last "Str" 3) (a b)) [2 4 6 9 23] [2 4 6 [8 9] [10 11] 9 23] {:de "Deutschland", :fr "France"} #{"Bread" "Cheese" "Wine"}

Thursday, April 19, 12

Clojure: Datenstrukturen
Numbers Strings Characters Keywords Symbols Regexps Lists Vectors Maps Sets
2 3 4 0.234 3/5 -2398989892820093093090292321 "Hello" "World" \a \b \c :first :last a b c #"Ch.*se" (a b c) ((:first :last "Str" 3) (a b)) [2 4 6 9 23] [2 4 6 [8 9] [10 11] 9 23] {:de "Deutschland", :fr "France"} #{"Bread" "Cheese" "Wine"}

Thursday, April 19, 12

Clojure: Datenstrukturen
Numbers Strings Characters Keywords Symbols Regexps Lists Vectors Maps Sets
2 3 4 0.234 3/5 -2398989892820093093090292321 "Hello" "World" \a \b \c :first :last a b c #"Ch.*se" (a b c) ((:first :last "Str" 3) (a b)) [2 4 6 9 23] [2 4 6 [8 9] [10 11] 9 23] {:de "Deutschland", :fr "France"} #{"Bread" "Cheese" "Wine"}

Thursday, April 19, 12

Clojure: Datenstrukturen
Numbers Strings Characters Keywords Symbols Regexps Lists Vectors Maps Sets
2 3 4 0.234 3/5 -2398989892820093093090292321 "Hello" "World" \a \b \c :first :last a b c #"Ch.*se" (a b c) ((:first :last "Str" 3) (a b)) [2 4 6 9 23] [2 4 6 [8 9] [10 11] 9 23] {:de "Deutschland", :fr "France"} #{"Bread" "Cheese" "Wine"}

Thursday, April 19, 12

Clojure: Datenstrukturen
Numbers Strings Characters Keywords Symbols Regexps Lists Vectors Maps Sets
2 3 4 0.234 3/5 -2398989892820093093090292321 "Hello" "World" \a \b \c :first :last a b c #"Ch.*se" (a b c) ((:first :last "Str" 3) (a b)) [2 4 6 9 23] [2 4 6 [8 9] [10 11] 9 23] {:de "Deutschland", :fr "France"} #{"Bread" "Cheese" "Wine"}

Thursday, April 19, 12

Clojure: Datenstrukturen
Numbers Strings Characters Keywords Symbols Regexps Lists Vectors Maps Sets
2 3 4 0.234 3/5 -2398989892820093093090292321 "Hello" "World" \a \b \c :first :last a b c #"Ch.*se" (a b c) ((:first :last "Str" 3) (a b)) [2 4 6 9 23] [2 4 6 [8 9] [10 11] 9 23] {:de "Deutschland", :fr "France"} #{"Bread" "Cheese" "Wine"}

Thursday, April 19, 12

Clojure: Datenstrukturen
Numbers Strings Characters Keywords Symbols Regexps Lists Vectors Maps Sets
2 3 4 0.234 3/5 -2398989892820093093090292321 "Hello" "World" \a \b \c :first :last a b c #"Ch.*se" (a b c) ((:first :last "Str" 3) (a b)) [2 4 6 9 23] [2 4 6 [8 9] [10 11] 9 23] {:de "Deutschland", :fr "France"} #{"Bread" "Cheese" "Wine"}

Thursday, April 19, 12

Syntax

Thursday, April 19, 12

Youve just seen it Rich Hickey

Thursday, April 19, 12

(ns sample.grep !!"A simple complete Clojure program." !!(:use [clojure.contrib.io :only [read-lines]]) !!(:gen-class)) (defn numbered-lines [lines] !!(map vector (iterate inc 0) lines))

Clojure: Beispie;l

(defn grep-in-file [pattern file] !!{file (filter #(re-find pattern (second %)) (numbered-lines (read-lines file)))}) (defn grep-in-files [pattern files] !!(apply merge (map #(grep-in-file pattern %) files))) (defn print-matches [matches] !!(doseq [[fname submatches] matches, [line-no, match] submatches] !!!!(println (str fname ":" line-no ":" match)))) !!!!!!!!!!!! (defn -main [pattern & files] !!(if (or (nil? pattern) (empty? files)) !!!!(println "Usage: grep <pattern> <file...>") !!!!(do !!!!!!(println (format "grep started with pattern %s and file(s) %s" pattern (apply str (interpose ", " files)))) !!!!!!(print-matches (grep-in-files (re-pattern pattern) files)) !!!!!!(println "Done."))))

Thursday, April 19, 12

(ns sample.grep !!"A simple complete Clojure program." !!(:use [clojure.contrib.io :only [read-lines]]) !!(:gen-class)) (defn numbered-lines [lines] !!(map vector (iterate inc 0) lines))

Clojure: Beispie;l

(defn grep-in-file [pattern file] !!{file (filter #(re-find pattern (second %)) (numbered-lines (read-lines file)))}) (defn grep-in-files [pattern files] !!(apply merge (map #(grep-in-file pattern %) files))) (defn print-matches [matches] !!(doseq [[fname submatches] matches, [line-no, match] submatches] !!!!(println (str fname ":" line-no ":" match)))) !!!!!!!!!!!! (defn -main [pattern & files] !!(if (or (nil? pattern) (empty? files)) !!!!(println "Usage: grep <pattern> <file...>") !!!!(do !!!!!!(println (format "grep started with pattern %s and file(s) %s" pattern (apply str (interpose ", " files)))) !!!!!!(print-matches (grep-in-files (re-pattern pattern) files)) !!!!!!(println "Done."))))

Thursday, April 19, 12

(ns sample.grep !!"A simple complete Clojure program." !!(:use [clojure.contrib.io :only [read-lines]]) !!(:gen-class)) (defn numbered-lines [lines] !!(map vector (iterate inc 0) lines))

Clojure: Beispie;l

(defn grep-in-file [pattern file] !!{file (filter #(re-find pattern (second %)) (numbered-lines (read-lines file)))}) (defn grep-in-files [pattern files] !!(apply merge (map #(grep-in-file pattern %) files))) (defn print-matches [matches] !!(doseq [[fname submatches] matches, [line-no, match] submatches] !!!!(println (str fname ":" line-no ":" match)))) !!!!!!!!!!!! (defn -main [pattern & files] !!(if (or (nil? pattern) (empty? files)) !!!!(println "Usage: grep <pattern> <file...>") !!!!(do !!!!!!(println (format "grep started with pattern %s and file(s) %s" pattern (apply str (interpose ", " files)))) !!!!!!(print-matches (grep-in-files (re-pattern pattern) files)) !!!!!!(println "Done."))))

Thursday, April 19, 12

(ns sample.grep !!"A simple complete Clojure program." !!(:use [clojure.contrib.io :only [read-lines]]) !!(:gen-class)) (defn numbered-lines [lines] !!(map vector (iterate inc 0) lines))

Clojure: Beispie;l

(defn grep-in-file [pattern file] !!{file (filter #(re-find pattern (second %)) (numbered-lines (read-lines file)))}) (defn grep-in-files [pattern files] !!(apply merge (map #(grep-in-file pattern %) files))) (defn print-matches [matches] !!(doseq [[fname submatches] matches, [line-no, match] submatches] !!!!(println (str fname ":" line-no ":" match)))) !!!!!!!!!!!! (defn -main [pattern & files] !!(if (or (nil? pattern) (empty? files)) !!!!(println "Usage: grep <pattern> <file...>") !!!!(do !!!!!!(println (format "grep started with pattern %s and file(s) %s" pattern (apply str (interpose ", " files)))) !!!!!!(print-matches (grep-in-files (re-pattern pattern) files)) !!!!!!(println "Done."))))

Thursday, April 19, 12

(ns sample.grep !!"A simple complete Clojure program." !!(:use [clojure.contrib.io :only [read-lines]]) !!(:gen-class)) (defn numbered-lines [lines] !!(map vector (iterate inc 0) lines))

Clojure: Beispie;l

(defn grep-in-file [pattern file] !!{file (filter #(re-find pattern (second %)) (numbered-lines (read-lines file)))}) (defn grep-in-files [pattern files] !!(apply merge (map #(grep-in-file pattern %) files))) (defn print-matches [matches] !!(doseq [[fname submatches] matches, [line-no, match] submatches] !!!!(println (str fname ":" line-no ":" match)))) !!!!!!!!!!!! (defn -main [pattern & files] !!(if (or (nil? pattern) (empty? files)) !!!!(println "Usage: grep <pattern> <file...>") !!!!(do !!!!!!(println (format "grep started with pattern %s and file(s) %s" pattern (apply str (interpose ", " files)))) !!!!!!(print-matches (grep-in-files (re-pattern pattern) files)) !!!!!!(println "Done."))))

Thursday, April 19, 12

(ns sample.grep !!"A simple complete Clojure program." !!(:use [clojure.contrib.io :only [read-lines]]) !!(:gen-class)) (defn numbered-lines [lines] !!(map vector (iterate inc 0) lines))

Clojure: Beispie;l

(defn grep-in-file [pattern file] !!{file (filter #(re-find pattern (second %)) (numbered-lines (read-lines file)))}) (defn grep-in-files [pattern files] !!(apply merge (map #(grep-in-file pattern %) files))) (defn print-matches [matches] !!(doseq [[fname submatches] matches, [line-no, match] submatches] !!!!(println (str fname ":" line-no ":" match)))) !!!!!!!!!!!! (defn -main [pattern & files] !!(if (or (nil? pattern) (empty? files)) !!!!(println "Usage: grep <pattern> <file...>") !!!!(do !!!!!!(println (format "grep started with pattern %s and file(s) %s" pattern (apply str (interpose ", " files)))) !!!!!!(print-matches (grep-in-files (re-pattern pattern) files)) !!!!!!(println "Done."))))

Thursday, April 19, 12

Clojure: Features
Persistent data structures Support for concurrent programming Sequences Destructuring List comprehensions Metadata Optiional type information Multimethods Pre & Post Conditions Records/Protocols Extensive core and contrib libraries
Thursday, April 19, 12

Clojure: Features
Persistent data structures Support for concurrent programming Sequences Destructuring List comprehensions Metadata Optiional type information Multimethods Pre & Post Conditions Records/Protocols Extensive core and contrib libraries
Thursday, April 19, 12

4711: Person rst: John last: Smith

Thursday, April 19, 12

4711: Person rst: John last: Smith

Thursday, April 19, 12

4711: Person rst: John last: Smith

Thursday, April 19, 12

4711: Person rst: John last: Smith 0815: Person rst: Jane last: Doe

Thursday, April 19, 12

4711: Person rst: John last: Smith 0815: Person rst: Jane last: Doe

Thursday, April 19, 12

4711: Person rst: John last: Smith 0815: Person rst: Jane last: Doe

Thursday, April 19, 12

4711: Person rst: John last: Smith 0815: Person rst: Jane last: Doe

Thursday, April 19, 12

4711: Person rst: John last: Smith 0815: Person rst: Jane last: Doe

Thursday, April 19, 12

4711: Person rst: John last: Smith 0815: Person rst: Jane last: Doe

Thursday, April 19, 12

4711: Person rst: John last: Smith 0815: Person rst: Jane last: Doe

The Problem!

Thursday, April 19, 12

Immutability

Thursday, April 19, 12

Immutability
user> (def v (vec (range 10)))

Thursday, April 19, 12

Immutability
user> (def v (vec (range 10))) #'user/v

Thursday, April 19, 12

Immutability
user> (def v (vec (range 10))) #'user/v user> v

Thursday, April 19, 12

Immutability
user> (def v (vec (range 10))) #'user/v user> v [0 1 2 3 4 5 6 7 8 9]

Thursday, April 19, 12

Immutability
user> (def v (vec (range 10))) #'user/v user> v [0 1 2 3 4 5 6 7 8 9] user> (assoc v 1 99)

Thursday, April 19, 12

Immutability
user> (def v (vec (range 10))) #'user/v user> v [0 1 2 3 4 5 6 7 8 9] user> (assoc v 1 99) [0 99 2 3 4 5 6 7 8 9]

Thursday, April 19, 12

Immutability
user> (def v (vec (range 10))) #'user/v user> v [0 1 2 3 4 5 6 7 8 9] user> (assoc v 1 99) [0 99 2 3 4 5 6 7 8 9] user> v

Thursday, April 19, 12

Immutability
user> (def v (vec (range 10))) #'user/v user> v [0 1 2 3 4 5 6 7 8 9] user> (assoc v 1 99) [0 99 2 3 4 5 6 7 8 9] user> v [0 1 2 3 4 5 6 7 8 9]

Thursday, April 19, 12

Immutability
user> (def v (vec (range 10))) #'user/v user> v [0 1 2 3 4 5 6 7 8 9] user> (assoc v 1 99) [0 99 2 3 4 5 6 7 8 9] user> v [0 1 2 3 4 5 6 7 8 9] user> (def v2 (assoc v 1 99))

Thursday, April 19, 12

Immutability
user> (def v (vec (range 10))) #'user/v user> v [0 1 2 3 4 5 6 7 8 9] user> (assoc v 1 99) [0 99 2 3 4 5 6 7 8 9] user> v [0 1 2 3 4 5 6 7 8 9] user> (def v2 (assoc v 1 99)) #'user/v2

Thursday, April 19, 12

Immutability
user> (def v (vec (range 10))) #'user/v user> v [0 1 2 3 4 5 6 7 8 9] user> (assoc v 1 99) [0 99 2 3 4 5 6 7 8 9] user> v [0 1 2 3 4 5 6 7 8 9] user> (def v2 (assoc v 1 99)) #'user/v2 user> v2

Thursday, April 19, 12

Immutability
user> (def v (vec (range 10))) #'user/v user> v [0 1 2 3 4 5 6 7 8 9] user> (assoc v 1 99) [0 99 2 3 4 5 6 7 8 9] user> v [0 1 2 3 4 5 6 7 8 9] user> (def v2 (assoc v 1 99)) #'user/v2 user> v2 [0 99 2 3 4 5 6 7 8 9]

Thursday, April 19, 12

user> (def v (vec (range 10)))

Thursday, April 19, 12

user> (def v (vec (range 10))) user> (def v2 (assoc v 1 99))

Thursday, April 19, 12

user> (def v (vec (range 10))) user> (def v2 (assoc v 1 99))

99

Thursday, April 19, 12

user> (def v (vec (range 10))) user> (def v2 (assoc v 1 99))

99

Thursday, April 19, 12

user> (def v (vec (range 10))) user> (def v2 (assoc v 1 99))

99

Thursday, April 19, 12

user> (def v (vec (range 10))) user> (def v2 (assoc v 1 99))

v2

99

Thursday, April 19, 12

Persistent Data Structures


Pure functional programming model Efficient implementation Structural sharing Thread-safe Iteration-safe Based on Bit-partioned hash tries

Thursday, April 19, 12

Performance Guarantees
hash-map sorted-map hash-set sorted-set vector queue list lazy seq

conj assoc dissoc disj nth get pop peek count


Thursday, April 19, 12

nearconstant nearconstant nearconstant -

logarith mic logarith mic logarith mic -

nearlogarith constant mic -

constant (tail) nearconstant -

constant constant constant (tail) (head) (head) linear constant (head) constant (head) constant linear constant (head) constant (head) constant linear constant (head) constant (head) linear

nearconstant nearlogarith nearlogarith nearconstant mic constant mic constant constant (tail) constant (tail) constant constant constant constant constant

nearlogarith constant mic -

Clojure: Software Transactional Memory (1)


(defn make-account !![balance owner] !!{:balance balance, :owner owner})

Thursday, April 19, 12

Clojure: Software Transactional Memory (1)


(defn make-account !![balance owner] !!{:balance balance, :owner owner})

(defn withdraw [account amount] !!(assoc account :balance (- (account :balance) amount)))

Thursday, April 19, 12

Clojure: Software Transactional Memory (1)


(defn make-account !![balance owner] !!{:balance balance, :owner owner})

(defn withdraw [account amount] !!(assoc account :balance (- (account :balance) amount)))

(defn deposit [account amount] !!(assoc account :balance (+ (account :balance) amount)))

Thursday, April 19, 12

Clojure: Software Transactional Memory (2)


(defn transfer !![from to amount] !!(dosync !! (alter from withdraw amount) !! (alter to deposit amount))) (defn init-accounts [] !!(def acc1 (ref (make-account 1000 "alice"))) !!(def acc2 (ref (make-account 1000 "bob"))) !!(def acc3 (ref (make-account 1000 "charles"))))

Thursday, April 19, 12

Clojure: Software Transactional Memory (2)


(defn transfer !![from to amount] !!(dosync !! (alter from withdraw amount) !! (alter to deposit amount))) (defn init-accounts [] !!(def acc1 (ref (make-account 1000 "alice"))) !!(def acc2 (ref (make-account 1000 "bob"))) !!(def acc3 (ref (make-account 1000 "charles"))))

Thursday, April 19, 12

Clojure: Software Transactional Memory (3)


(init-accounts) acc1: {:balance 1000, :owner "alice"} acc2: {:balance 1000, :owner "bob"} acc3: {:balance 1000, :owner "charles"} (do (run-thread-fn #(transfer acc1 acc2 100)) (transfer acc3 acc1 400))

acc1: {:balance 1300, :owner "alice"} acc2: {:balance 1100, :owner "bob"} acc3: {:balance 600, :owner "charles"}

Thursday, April 19, 12

Clojure: Kernkonzepte
Funktionale Programmierung Homoikonizitt Software Transactional Memory

Thursday, April 19, 12

Clojure: Praxistauglichkeit
Technisch: Einsatzfhig und praxistauglich Politisch: Schwer durchsetzbar (?) Chance und Risiko Nische: Concurrent and Correct

Thursday, April 19, 12

Clojure: Java-Bibliotheken
Functional Java (http://functionaljava.org/) Google Guava java.util.concurrent JDK 8 (ParallelArray & Co.) bzw. JSR 166y

Thursday, April 19, 12

Clojure: Java-Idiome
Immutability Anonymous Inner Classes Daten statt spezifische Klassen

Thursday, April 19, 12

Erlang

Thursday, April 19, 12

Von Prolog zu Erlang


Ericsson-Experimente zur Hchstverfgbarkeit (>> 99.999%) Implementierung von Telekom-Services in verschiedenen Sprachen Anforderungen: Zuverlssigkeit, Parallelitt Konventionelle Sprachen (u.a. C, C++) schnitten schlecht ab... (aber Prolog fhlte
sich gut an)

Thursday, April 19, 12

Erlang Beispiel

Aus: Cesarini & Thompson: Erlang Programming (OReilly, 2009)


Thursday, April 19, 12

Erlang - Theorie

Compiler (erlc) bersetzt in beam Format


(Bogumil Erlang Abstract Machine)

Virtuelle Maschine fhrt beam-Code aus Write-Once, Run-Anywhere


(verhlt sich berall identisch - wenns luft, dann richtig)

Thursday, April 19, 12

Erlang - Theorie
Verteilung auf Knoten (Erlang-Nodes) Viele Knoten pro physischer Hardware (SEHR) viele ErlangProzesse pro Knoten
Thursday, April 19, 12

Erlang Node Physical Node

call functions

Erlang - Womit?
Emacs + make + Shell % for hardcore-geeks

Texteditor + Shell + rebar % erlang build + test tool Eclipse + erlide

Thursday, April 19, 12

Erlang IDE in Eclipse 3.7


Thursday, April 19, 12

Erlang - Theorie
123, 17.4, abcd, start_with_lowercase, quoted with blanks

Zahlen, Atome Tupel Listen

{123, bcd} {123, def, abc} {person, 'Joe', Armstrong'}

[1,2] [abc, def] [{person,'Joe'}, {special,'42'}]

Thursday, April 19, 12

Erlang - Theorie
A = 10 ! Erfolg - bindet A an 10

PatternMatching

{B, C, D} = {10, foo, bar} Erfolg - bindet B an 10, C an foo und D an bar {A, A, B} = {abc, abc, foo} ! Erfolg - bindet A an abc, B an foo ! {A, A, B} = {abc, def, 123} ! Fail

Thursday, April 19, 12

Erlang - Theorie

Funktionen

-module(mathStuff). ! -export([factorial/1, area/1]). ! factorial(0) -> 1; factorial(N) -> N * factorial(N-1). ! area({square, Side}) -> ! ! Side * Side; area({circle, Radius}) -> ! ! % almost :-) ! ! 3 * Radius * Radius; area(Other) -> ! ! {invalid_object, Other}.

Thursday, April 19, 12

Prozesse

Erlang - Theorie

Bestandteil der Sprache Ausgefhrt innerhalb der Erlang-VM

PID A
PID = spawn( foo ). B! {self(), foo}.

foo

PID B
receive {A, foo"} -> fn_foo; end.

Thursday, April 19, 12

Erlang - process spawning


Test (von Joe Armstrong)
Messe spawn-Zeit von Erlang Prozessen Vereinfachung: Innerhalb EINER VM
max(N) -> ! Max = erlang:system_info(process_limit), ! io:format("Maximum allowed processes: ~p~n", [Max]), ! statistics(runtime), ! statistics(wall_clock), ! L = for( 1, N, fun() -> spawn(fun() -> wait() end) end), ! {_, Time1} = statistics(runtime), ! {_, Time2} = statistics(wall_clock), ! lists:foreach(fun(Pid) -> Pid ! die end, L), ! U1 = Time1 * 1000 / N, ! U2 = Time2 * 1000 / N, ! io:format("Process spawn time=~p (~p) microseconds~n", [U1, U2]).

Thursday, April 19, 12

erlang process timer

2 sec (CPU-Zeit) 3.2 sec (Realzeit)


>> 100.000 Prozesse pro Sekunde limitiert primr durch RAM der Erlang-VM
Thursday, April 19, 12

Erlang: Kernkonzepte
Funktionale Programmierung Aktormodell Leichtgewichtige Prozesse Hot Swapping

Thursday, April 19, 12

Erlang: Praxistauglichkeit
Erprobt Server mit vielen parallelen Zugriffen (Protokollserver, Datenbanken, ) Systeme mit hchsten VerfgbarkeitsAnforderungen

Thursday, April 19, 12

Erlang: Beispiele
CouchDB Facebook-Chat RIAK Scalaris
(transaktionale, hoch skalierbare in-memory DB)

ejabberd Disco
(MapReduce von Nokia)

Membase Cluster Manager


Wahrscheinlich:

Amazon SimpleDB

Thursday, April 19, 12

Erlang: Java-Bibliotheken
Akka (http://akka.io/) Kilim (http://www.malhar.net/sriram/ kilim/)

Thursday, April 19, 12

Erlang: Java-Idiome
Immutability, Anonymous Inner Classes Active Objects Message Queues

Thursday, April 19, 12

Node.js

Thursday, April 19, 12

Node.js-Architektur
API (JavaScript)

Network/Platform layer (C)

v8

libev

libeio

http_parser

c_ares

Thursday, April 19, 12

High-performance network runtime, using JavaScript as a high-level DSL

Thursday, April 19, 12

var net = require('net'); var server = net.createServer(function (socket) { socket.write("Echo server\r\n"); socket.pipe(socket); }) server.listen(8124, "127.0.0.1");

Beispiele: http://github.com/stilkov/node-samples

echo.js
Thursday, April 19, 12

var net = require('net'); var server = net.createServer(function (socket) { socket.write("Echo server\r\n"); socket.setEncoding('ascii'); socket.on('data', function(data) { socket.write(data.toUpperCase()); }); }); server.listen(8124, "127.0.0.1");

echo-upcase.js
Thursday, April 19, 12

var sys = require("sys"), http = require("http"), url = require("url"), path = require("path"), fs = require("fs"); var dir = process.argv[2] || './public'; var port = parseFloat(process.argv[3]) || 8080; sys.log('Serving files from ' + dir + ', port is ' + port); http.createServer(function(request, response) { var uri = url.parse(request.url).pathname; var filename = path.join(process.cwd(), dir, uri); path.exists(filename, function(exists) { if(exists) { fs.readFile(filename, function(err, data) { response.writeHead(200); response.end(data); }); } else { sys.log('File not found: ' + filename); response.writeHead(404); response.end(); } }); }).listen(port);

file-server.js
Thursday, April 19, 12

Concurrency Level: Time taken for tests: Complete requests: Failed requests: Write errors: Keep-Alive requests: Total transferred: HTML transferred: Requests per second: Time per request: Time per request: Transfer rate:

100 6.000 seconds 10000 0 0 0 710781 bytes 150165 bytes 1666.72 [#/sec] (mean) 59.998 [ms] (mean) 0.600 [ms] (mean, across all concurrent requests) 115.69 [Kbytes/sec] received

Connection Times (ms) min mean[+/-sd] median Connect: 0 8 8.3 5 Processing: 1 51 44.4 40 Waiting: 0 43 43.5 30 Total: 1 59 44.8 50

max 57 307 302 316

Percentage of the requests served within a certain time (ms) 50% 50 66% 58 75% 68 80% 73 90% 112 95% 174 98% 206 99% 224 100% 316 (longest request)

Thursday, April 19, 12

http.createServer(function(request, response) { var uri = url.parse(request.url).pathname; var filename = path.join(process.cwd(), dir, uri); path.exists(filename, function(exists) { if(exists) { f = fs.createReadStream(filename); f.on('open', function() { response.writeHead(200); }); f.on('data', function(chunk) { response.write(chunk); }); f.on('error', function(err) { // ... }); f.on('end', function() { response.end(); }); } else { response.writeHead(404); response.end(); }

}); }).listen(port);

stream-file-server.js
Thursday, April 19, 12

var options = function(request) { // ... } http.createServer(function(request, response) { sys.log("--> " + request.url); var remoteRequest = http.request(options(request), function (remoteResponse) { response.writeHead(remoteResponse.statusCode, remoteResponse.headers); remoteResponse.on('data', function (chunk) { response.write(chunk); }); remoteResponse.on('end', function () { sys.log("<-- " + response.statusCode + " " + request.url); response.end(); }); }); request.on('data', function (chunk) { remoteRequest.write(chunk); }); request.on('end', function () { remoteRequest.end(); }); }).listen(port);

proxy.js
Thursday, April 19, 12

http.createServer(function(request, response) { sys.log("--> " + request.url); var remoteRequest = http.request(options(request), function (remoteResponse) { response.writeHead(remoteResponse.statusCode, remoteResponse.headers); remoteResponse.on('end', function () { sys.log("<-- " + response.statusCode + " " + request.url); }); util.pump(remoteResponse, response); }); util.pump(request, remoteRequest); }).listen(port);

proxy-pump.js
Thursday, April 19, 12

Thursday, April 19, 12

Node.js: Kernkonzepte
Async I/O Events & Callbacks Single Process Model

Thursday, April 19, 12

Node.js: Praxistauglichkeit
Sehr jung, aber sehr aktiv Web 2.0-Umfeld Hufig: Vereinfachung

Thursday, April 19, 12

Node.js: Java-Bibliotheken
java.nio java.nio2 Netty (http://www.jboss.org/netty) Grizzly (http://grizzly.java.net/) Vert.x (https://github.com/purplefox/vert.x) Project Nashorn

Thursday, April 19, 12

Fazit

Thursday, April 19, 12

1. Es gibt ein Leben jenseits von Java

Thursday, April 19, 12

2. Alternativen knnen in der Praxis sinnvoll sein

Thursday, April 19, 12

3. Die Beschftigung lohnt auch 100%-Java-Entwickler

Thursday, April 19, 12

Q&A

Thursday, April 19, 12

Q&A

Dr. Gernot Starke gernot.starke@innoq.com gs@gernotstarke.de

Stefan Tilkov stefan.tilkov@innoq.com @stilkov


innoQ Deutschland GmbH Krischerstr. 100 40789 Monheim am Rhein Germany Phone: +49 2173 3366-0 http://www.innoq.com innoQ Schweiz GmbH Gewerbestr. 11 CH-6330 Cham Switzerland Phone: +41 41 743 0116 info@innoq.com

2012 innoQ Deutschland GmbH Thursday, April 19, 12

You might also like