Sie sind auf Seite 1von 120
Gernot Starke & Stefan Tilkow | innoQ Erlang, Clojure & Co.: Was der Mainstream von
Gernot Starke & Stefan Tilkow | innoQ Erlang, Clojure & Co.: Was der Mainstream von
Gernot Starke & Stefan Tilkow | innoQ Erlang, Clojure & Co.: Was der Mainstream von
Gernot Starke & Stefan Tilkow | innoQ Erlang, Clojure & Co.: Was der Mainstream von
Gernot Starke & Stefan Tilkow | innoQ Erlang, Clojure & Co.: Was der Mainstream von
Gernot Starke & Stefan Tilkow | innoQ Erlang, Clojure & Co.: Was der Mainstream von
Gernot Starke & Stefan Tilkow | innoQ Erlang, Clojure & Co.: Was der Mainstream von
Gernot Starke & Stefan Tilkow | innoQ Erlang, Clojure & Co.: Was der Mainstream von

Gernot Starke & Stefan Tilkow | innoQ

Erlang, Clojure & Co.:

Was der Mainstream von Alternativen lernen kann

Was Sie aus Prolog,

Erlang & Clojure

für den Mainstream lernen können

Gernot Starke, Stefan Tilkov

aus Prolog, Erlang & Clojure für den Mainstream lernen können Gernot Starke, Stefan Tilkov Thursday, April
aus Prolog, Erlang & Clojure für den Mainstream lernen können Gernot Starke, Stefan Tilkov Thursday, April

Wir über uns

Stefan Tilkov

Wir über uns Stefan Tilkov http://www.innoq.com Gernot Starke Thursday, April 19, 12
Wir über uns Stefan Tilkov http://www.innoq.com Gernot Starke Thursday, April 19, 12

http://www.innoq.com

Gernot Starke

Wir über uns Stefan Tilkov http://www.innoq.com Gernot Starke Thursday, April 19, 12

Prolog

Clojure

Erlang

Node.js

Prolog Clojure Erlang Node.js Thursday, April 19, 12

Kernkonzepte

Prolog

Clojure

Erlang

Node.js

Kernkonzepte Prolog Clojure Erlang Node.js Thursday, April 19, 12

Kernkonzepte

Praxistauglichkeit

Prolog

Clojure

Erlang

Node.js

Kernkonzepte Praxistauglichkeit Prolog Clojure Erlang Node.js Thursday, April 19, 12

Kernkonzepte

Praxistauglichkeit

Java-Bibliotheken

Prolog

Clojure

Erlang

Node.js

Kernkonzepte Praxistauglichkeit Java-Bibliotheken Prolog Clojure Erlang Node.js Thursday, April 19, 12

Kernkonzepte

Praxistauglichkeit

Java-Bibliotheken

Java-Idiome

Prolog

Clojure

Erlang

Node.js

Kernkonzepte Praxistauglichkeit Java-Bibliotheken Java-Idiome Prolog Clojure Erlang Node.js Thursday, April 19, 12

Prolog

Prolog Thursday, April 19, 12

Anforderungen

1. Es gibt fünf Häuser mit je einer anderen Farbe.

2. In jedem Haus wohnt eine Person anderer Nationalität.

3. Jeder Hausbewohner bevorzugt ein

bestimmtes Getränk, raucht eine bestimmte Zigarettenmarke und hält ein bestimmtes Haustier.

4. Keine der fünf Personen trinkt das gleiche Getränk, raucht die gleichen Zigaretten oder hält das gleiche Tier wie seine Nachbarn.

Frage: Wem gehört der Fisch?

Hinweise:

• Der Brite lebt im roten Haus.

• Der Schwede hält einen Hund.

• Der Däne trinkt gern Tee.

• Das grüne Haus steht direkt links neben dem weißen Haus.

• Der Besitzer des grünen Hauses trinkt Ka ee.

• Die Person, die Pall Mall raucht, hält 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 hält.

• Der Mann, der ein Pferd hält, wohnt neben dem, der Dunhill raucht.

• Der Win eld-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

Marlboro-Raucher hat einen Nachbarn, der Wasser trinkt. Angeblich nach Einstein, hier aus Wikipedia Thursday, April 19,

Lösung in Prolog

run :- X =[_,_,_,_,_],/* Es gibt (nebeneinander) 5 Häuser */ member([rot,brite,_,_,_],X),/* Der Brite lebt im roten Haus */ member([_,schwede,_,_,hund],X),/* Der Schwede hält einen Hund */ member([_,daene,tee,_,_],X),/* Der Däne trinkt gern Tee */ links([gruen,_,_,_,_],[weiss,_,_,_,_],X),/* Das grüne Haus steht links vom weißen Haus */ member([gruen,_,kaffee,_,_],X),/* Der Besitzer des grünen Hauses trinkt Kaffee */ member([_,_,_,pallmall,vogel],X),/* Die Person, die Pall Mall raucht, hält 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 Nationalität N hat einen Fisch */ write(X),nl,/* Ausgabe aller Häuser */ write('Der '),write(N),write(' hat einen Fisch als Haustier.'),nl.

write ( 'Der ' ) , write ( N ) , write ( ' hat einen

Lösung in Prolog

run :-

X =[_,_,_,_,_],/* Es gibt (nebeneinander) 5 Häuser */ member([rot,brite,_,_,_],X), /* Der Brite lebt im roten Haus */ member([_,schwede,_,_,hund],X), /* Der Schwede hält einen Hund */ member([_,daene,tee,_,_],X), /* Der Däne trinkt gern Tee */ links([gruen,_,_,_,_],[weiss,_,_,_,_],X), /* Das grüne Haus steht links vom weißen Haus */

%

_ , _ ] , [ weiss , _ , _ , _ , _ ]

Lösung 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).

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: „Uni kation 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

Prolog versucht, Wahrheit zu beweisen Beispiel: neben(A, b, [a,c,b,d]) -> A = c A = d

Prolog

Backtracking = systematisches Ausprobieren
Backtracking
=
systematisches
Ausprobieren
Prolog Backtracking = systematisches Ausprobieren Thursday, April 19, 12

Prolog: Kernkonzepte

Regelorientierung

Backtracking

Deklarativer Ansatz

Prolog: Kernkonzepte Regelorientierung Backtracking Deklarativer Ansatz Thursday, April 19, 12

Prolog: Praxistauglichkeit

Schwierig (riskant): Integration in Java- Mainstream

tu-Prolog als Eclipse-Plugin, experimentell + fragil

Gut geeignet für Planungsprobleme

Mainstream tu-Prolog als Eclipse-Plugin, experimentell + fragil Gut geeignet für Planungsprobleme Thursday, April 19, 12

Prolog: Java-Bibliotheken

Regelsysteme heute „geschä s- und integrationsfähig“:

kommerzielle Regel-Engines

freie Regel-Engine(s), etwa JBoss-Drools

s- und integrationsfähig“: kommerzielle Regel-Engines freie Regel-Engine(s), etwa JBoss-Drools Thursday, April 19, 12

JBoss Drools

JBoss Drools Thursday, April 19, 12
JBoss Drools Thursday, April 19, 12

Clojure

Clojure Thursday, April 19, 12
Clojure Thursday, April 19, 12

Clojure: Datenstrukturen

Clojure: Datenstrukturen Thursday, April 19, 12

Clojure: Datenstrukturen

Numbers

2 3 4 0.234 3/5 -2398989892820093093090292321

Clojure: Datenstrukturen Numbers 2 3 4 0.234 3/5 -2398989892820093093090292321 Thursday, April 19, 12

Clojure: Datenstrukturen

Numbers

2 3 4 0.234 3/5 -2398989892820093093090292321

Strings

"Hello" "World"

2 3 4 0.234 3/5 -2398989892820093093090292321 S t r i n g s "Hello" "World" Thursday,

Clojure: Datenstrukturen

Numbers

2 3 4 0.234 3/5 -2398989892820093093090292321

Strings

"Hello" "World"

Characters

\a \b \c

S t r i n g s "Hello" "World" Characters \a \b \c Thursday, April 19,

Clojure: Datenstrukturen

Numbers

2 3 4 0.234 3/5 -2398989892820093093090292321

Strings

"Hello" "World"

Characters

\a \b \c

Keywords

:first :last

i n g s "Hello" "World" Characters \a \b \c K e y w o r

Clojure: Datenstrukturen

Numbers

2 3 4 0.234 3/5 -2398989892820093093090292321

Strings

"Hello" "World"

Characters

\a \b \c

Keywords

:first :last

Symbols

a

b c

"World" Characters \a \b \c K e y w o r d s :first :last Symbols

Clojure: Datenstrukturen

Numbers

2 3 4 0.234 3/5 -2398989892820093093090292321

Strings

"Hello" "World"

Characters

\a \b \c

Keywords

:first :last

Symbols

a

b c

Regexps

#"Ch.*se"

\a \b \c K e y w o r d s :first :last Symbols a b

Clojure: Datenstrukturen

Numbers

2 3 4 0.234 3/5 -2398989892820093093090292321

Strings

"Hello" "World"

Characters

\a \b \c

Keywords

:first :last

Symbols

a

b c

Regexps

#"Ch.*se"

Lists

(a b c) ((:first :last "Str" 3) (a b))

e x p s # "Ch.*se" Lists ( a b c ) (( :first :last "Str"

Clojure: Datenstrukturen

Numbers

2 3 4 0.234 3/5 -2398989892820093093090292321

Strings

"Hello" "World"

Characters

\a \b \c

Keywords

:first :last

Symbols

a

b c

Regexps

#"Ch.*se"

Lists

(a b c) ((:first :last "Str" 3) (a b))

Vectors

[2 4 6 9 23] [2 4 6 [8 9] [10 11] 9 23]

c ) (( :first :last "Str" 3) (a b)) Vectors [2 4 6 9 23] [2

Clojure: Datenstrukturen

Numbers

2 3 4 0.234 3/5 -2398989892820093093090292321

Strings

"Hello" "World"

Characters

\a \b \c

Keywords

:first :last

Symbols

a

b c

Regexps

#"Ch.*se"

Lists

(a b c) ((:first :last "Str" 3) (a b))

Vectors

[2 4 6 9 23] [2 4 6 [8 9] [10 11] 9 23]

Maps

{:de "Deutschland", :fr "France"}

9 23] [2 4 6 [8 9] [10 11] 9 23] M a p s {

Clojure: Datenstrukturen

Numbers

2 3 4 0.234 3/5 -2398989892820093093090292321

Strings

"Hello" "World"

Characters

\a \b \c

Keywords

:first :last

Symbols

a

b c

Regexps

#"Ch.*se"

Lists

(a b c) ((:first :last "Str" 3) (a b))

Vectors

[2 4 6 9 23] [2 4 6 [8 9] [10 11] 9 23]

Maps

{:de "Deutschland", :fr "France"}

Sets

#{"Bread" "Cheese" "Wine"}

, :fr "France" } S e t s #{" Bread" "Cheese" "Wine" } Thursday, April 19,

Syntax

Syntax Thursday, April 19, 12

“You’ve just seen it” – Rich Hickey

“You’ve just seen it” – Rich Hickey Thursday, April 19, 12

Clojure: Beispie;l

(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))

(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."))))

files)))) (print-matches (grep-in-files (re-pattern pattern) files)) (println "Done." )))) Thursday, April 19, 12

Clojure: Beispie;l

(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))

(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."))))

files)))) (print-matches (grep-in-files (re-pattern pattern) files)) (println "Done." )))) Thursday, April 19, 12
files)))) (print-matches (grep-in-files (re-pattern pattern) files)) (println "Done." )))) Thursday, April 19, 12

Clojure: Beispie;l

(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))

(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
(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."))))

files)))) (print-matches (grep-in-files (re-pattern pattern) files)) (println "Done." )))) Thursday, April 19, 12

Clojure: Beispie;l

(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))

(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 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."))))

files)))) (print-matches (grep-in-files (re-pattern pattern) files)) (println "Done." )))) Thursday, April 19, 12

Clojure: Beispie;l

(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))

(defn grep-in-file [pattern file] {file (filter #(re-find pattern (second %)) (numbered-lines (read-lines file)))})
(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."))))

files)))) (print-matches (grep-in-files (re-pattern pattern) files)) (println "Done." )))) Thursday, April 19, 12

Clojure: Beispie;l

(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))
(defn numbered-lines [lines]
(map vector (iterate inc 0) lines))

(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."))))

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

Multimethods Pre & Post Conditions Records/Protocols Extensive core and contrib libraries … Thursday, April 19, 12

Clojure: Features

Clojure: Features Persistent data structures Support for concurrent programming Sequences Destructuring List

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

Multimethods Pre & Post Conditions Records/Protocols Extensive core and contrib libraries … Thursday, April 19, 12
4711: Person first: John last: Smith Thursday, April 19, 12
4711: Person first: John last: Smith Thursday, April 19, 12

4711: Person first: John last: Smith

4711: Person first: John last: Smith Thursday, April 19, 12
4711: Person first: John last: Smith
4711: Person
first: John
last: Smith
4711: Person first: John last: Smith Thursday, April 19, 12
4711: Person first: John last: Smith
4711: Person
first: John
last: Smith
4711: Person first: John last: Smith Thursday, April 19, 12
4711: Person first: John last: Smith
4711: Person
first: John
last: Smith

0815: Person first: Jane last: Doe

4711: Person first: John last: Smith 0815: Person first: Jane last: Doe Thursday, April 19, 12
4711: Person first: John last: Smith 0815: Person first: Jane last: Doe
4711: Person
first: John
last: Smith
0815: Person
first: Jane
last: Doe
4711: Person first: John last: Smith 0815: Person first: Jane last: Doe Thursday, April 19, 12
4711: Person first: John last: Smith 0815: Person first: Jane last: Doe
4711: Person
first: John
last: Smith
0815: Person
first: Jane
last: Doe
4711: Person first: John last: Smith 0815: Person first: Jane last: Doe Thursday, April 19, 12
4711: Person first: John last: Smith 0815: Person first: Jane last: Doe
4711: Person
first: John
last: Smith
0815: Person
first: Jane
last: Doe
4711: Person first: John last: Smith 0815: Person first: Jane last: Doe Thursday, April 19, 12
4711: Person first: John last: Smith 0815: Person first: Jane last: Doe Thursday, April 19, 12
4711: Person first: John last: Smith 0815: Person first: Jane last: Doe Thursday, April 19, 12
4711: Person first: John last: Smith 0815: Person first: Jane last: Doe
4711: Person
first: John
last: Smith
0815: Person
first: Jane
last: Doe
4711: Person first: John last: Smith 0815: Person first: Jane last: Doe Thursday, April 19, 12
4711: Person first: John last: Smith 0815: Person first: Jane last: Doe
4711: Person
first: John
last: Smith
0815: Person
first: Jane
last: Doe
4711: Person first: John last: Smith 0815: Person first: Jane last: Doe Thursday, April 19, 12
4711: Person first: John last: Smith 0815: Person first: Jane last: Doe The Problem!
4711: Person
first: John
last: Smith
0815: Person
first: Jane
last: Doe
The Problem!
4711: Person first: John last: Smith 0815: Person first: Jane last: Doe The Problem! Thursday, April

Immutability

Immutability Thursday, April 19, 12

Immutability

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

Immutability user> ( def v (vec ( range 10))) Thursday, April 19, 12

Immutability

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

Immutability user> ( def v (vec ( range 10))) #'user/v Thursday, April 19, 12

Immutability

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

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]

user> ( def v (vec ( range 10))) #'user/v user> v [0 1 2 3 4

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)

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

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 user> v [0 1 2 3 4 5 6 7 8 9] user> ( assoc

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

user> v [0 1 2 3 4 5 6 7 8 9] user> ( assoc v

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]

4 5 6 7 8 9] user> ( assoc v 1 99) [0 99 2 3

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))

[0 99 2 3 4 5 6 7 8 9] user> v [0 1 2 3

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

6 7 8 9] user> v [0 1 2 3 4 5 6 7 8 9]

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

v [0 1 2 3 4 5 6 7 8 9] user> ( def v2 (

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]

6 7 8 9] user> ( def v2 ( assoc v 1 99)) #'user/v2 user> v2

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

v 7 9 2 4 0 1 3 5 6 8
v
7
9
2
4
0
1
3
5
6
8
user> ( def v (vec ( range 10))) v 7 9 2 4 0 1 3

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

v 7 9 2 4 0 1 3 5 6 8
v
7
9
2
4
0
1
3
5
6
8
v (vec ( range 10))) user> ( def v2 ( assoc v 1 99)) v 7

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

v 7 9 2 4 0 1 3 5 6 8 99
v
7
9
2
4
0
1
3
5
6
8
99
v (vec ( range 10))) user> ( def v2 ( assoc v 1 99)) v 7

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

v 7 9 2 4 0 1 3 5 6 8 99
v
7
9
2
4
0
1
3
5
6
8
99
v (vec ( range 10))) user> ( def v2 ( assoc v 1 99)) v 7

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

v 7 9 2 4 0 1 3 5 6 8 99
v
7
9
2
4
0
1
3
5
6
8
99
v (vec ( range 10))) user> ( def v2 ( assoc v 1 99)) v 7

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

v2 v 7 9 2 4 0 1 3 5 6 8 99
v2
v
7
9
2
4
0
1
3
5
6
8
99
( range 10))) user> ( def v2 ( assoc v 1 99)) v2 v 7 9

Persistent Data Structures

Pure functional programming model

E cient implementation

Structural sharing

Thread-safe

Iteration-safe

Based on Bit-partioned hash tries

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

near-

logarith

near-

logarith

constant

constant

constant

constant

constant

mic

constant

mic

(tail)

(tail)

(head)

(head)

assoc

near-

logarith

-

-

near-

-

-

-

constant

mic

constant

dissoc

near-

logarith

-

-

-

-

-

-

constant

mic

disj

-

-

near-

logarith

-

-

-

-

constant

mic

nth

-

-

-

-

near-

linear

linear

linear

constant

get

near-

logarith

near-

logarith

near-

-

-

-

constant

mic

constant

mic

constant

pop

-

-

-

-

constant

constant

constant

constant

(tail)

(head)

(head)

(head)

peek

-

-

-

-

constant

constant

constant

constant

(tail)

(head)

(head)

(head)

count

constant

constant

constant

constant

constant

constant

constant

linear

Clojure: So ware Transactional Memory (1)

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

Memory (1) ( defn make-account [balance owner] { :balance balance, :owner owner}) Thursday, April 19, 12

Clojure: So ware Transactional Memory (1)

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

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

( defn withdraw [account amount] ( assoc account :balance (- (account :balance ) amount))) Thursday, April

Clojure: So ware 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)))

( defn deposit [account amount] ( assoc account :balance (+ (account :balance ) amount))) Thursday, April

Clojure: So ware 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"))))

(make-account 1000 "bob" ))) ( def acc3 (ref (make-account 1000 "charles" )))) Thursday, April 19, 12

Clojure: So ware Transactional Memory (2)

(defn transfer [from to amount] (dosync (alter from withdraw amount) (alter to deposit amount)))

( alter from withdraw amount) ( alter to deposit amount))) ( defn init-accounts [] ( def

(defn init-accounts [] (def acc1 (ref (make-account 1000 "alice"))) (def acc2 (ref (make-account 1000 "bob"))) (def acc3 (ref (make-account 1000 "charles"))))

(make-account 1000 "bob" ))) ( def acc3 (ref (make-account 1000 "charles" )))) Thursday, April 19, 12

Clojure: So ware 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"}

{ :balance 1100, :owner "bob" } acc3: { :balance 600, :owner "charles" } Thursday, April 19,

Clojure: Kernkonzepte

Funktionale Programmierung

Homoikonizität

So ware Transactional Memory

Clojure: Kernkonzepte Funktionale Programmierung Homoikonizität So ware Transactional Memory Thursday, April 19, 12

Clojure: Praxistauglichkeit

Technisch: Einsatzfähig und praxistauglich

Politisch:

Schwer durchsetzbar (?)

Chance und Risiko

“Nische”: “Concurrent and Correct”

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

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 spezi sche Klassen

Clojure: Java-Idiome Immutability Anonymous Inner Classes Daten statt spezi sche Klassen Thursday, April 19, 12

Erlang

Erlang Thursday, April 19, 12
Erlang Thursday, April 19, 12

Von Prolog zu Erlang

Ericsson-Experimente zur Höchstverfügbarkeit (>> 99.999%)

Implementierung von Telekom-Services in verschiedenen Sprachen

Anforderungen: Zuverlässigkeit, Parallelität

Konventionelle Sprachen (u.a. C, C++)

schnitten schlecht ab

sich gut an“)

(aber Prolog „fühlte

Konventionelle Sprachen (u.a. C, C++) schnitten schlecht ab sich gut an“) (aber Prolog „fühlte Thursday, April

Erlang Beispiel

Erlang Beispiel Aus: Cesarini & Thompson: Erlang Programming (O‘Reilly, 2009) Thursday, April 19, 12

Aus: Cesarini & Thompson: Erlang Programming (O‘Reilly, 2009)

Erlang Beispiel Aus: Cesarini & Thompson: Erlang Programming (O‘Reilly, 2009) Thursday, April 19, 12

Erlang - Theorie

Compiler (erlc) übersetzt in „beam“ Format

(Bogumil Erlang Abstract Machine)

Virtuelle Maschine führt beam-Code aus

Write-Once, Run-Anywhere

(verhält sich überall identisch - wenn‘s läu , dann richtig)

aus Write-Once, Run-Anywhere (verhält sich überall identisch - wenn‘s läu , dann richtig) Thursday, April 19,

Erlang - Theorie

Verteilung auf „Knoten“ (Erlang-Nodes)

Viele Knoten pro physischer Hardware

(SEHR) viele Erlang- Prozesse pro Knoten

physischer Hardware (SEHR) viele Erlang- Prozesse pro Knoten Erlang Node Physical Node call functions Thursday, April
Erlang Node Physical Node
Erlang
Node
Physical
Node
Hardware (SEHR) viele Erlang- Prozesse pro Knoten Erlang Node Physical Node call functions Thursday, April 19,

call

functions

Hardware (SEHR) viele Erlang- Prozesse pro Knoten Erlang Node Physical Node call functions Thursday, April 19,

Erlang - Womit?

Emacs + make + Shell

Texteditor + Shell + rebar

Eclipse + erlide

% for hardcore-geeks

% erlang build + test tool

+ Shell Texteditor + Shell + rebar Eclipse + erlide % for hardcore-geeks % erlang build
Erlang IDE in Eclipse 3.7 Thursday, April 19, 12

Erlang IDE in Eclipse 3.7

Erlang IDE in Eclipse 3.7 Thursday, April 19, 12

Erlang - Theorie

123, 17.4, abcd, start_with_lowercase, ´quoted with blanks´
123, 17.4,
abcd, start_with_lowercase,
´quoted with blanks´
17.4, abcd, start_with_lowercase, ´quoted with blanks´ {123, bcd} {123, def, abc} {person, 'Joe',
{123, bcd} {123, def, abc} {person, 'Joe', Armstrong'}
{123, bcd}
{123, def, abc}
{person, 'Joe', Armstrong'}

Zahlen, Atome

abc} {person, 'Joe', Armstrong'} Zahlen, Atome Tupel Listen [1,2] [abc, def] [{person,'Joe'},

Tupel

Listen

'Joe', Armstrong'} Zahlen, Atome Tupel Listen [1,2] [abc, def] [{person,'Joe'},
[1,2] [abc, def] [{person,'Joe'}, {special,'42'}]
[1,2]
[abc, def]
[{person,'Joe'}, {special,'42'}]
Zahlen, Atome Tupel Listen [1,2] [abc, def] [{person,'Joe'}, {special,'42'}] Thursday, April 19, 12

Erlang - Theorie

Pattern-

Matching

A = 10

Erfolg - bindet A an 10

{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

= {abc, abc, foo} Erfolg - bindet A an abc, B an foo {A, A, B}
= {abc, abc, foo} Erfolg - bindet A an abc, B an foo {A, A, B}

Erlang - Theorie

Erlang - Theorie Funktionen -module(mathStuff).   -export([factorial/1, area/1]). factorial(0) -> 1;

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}.

almost :-) 3 * Radius * Radius; ! area(Other) ->   ! {invalid_object, Other}. Thursday, April

Prozesse

Erlang - Theorie

Bestandteil der Sprache

Ausgeführt innerhalb der Erlang-VM

Bestandteil der Sprache Ausgeführt innerhalb der Erlang-VM PID PID foo B A PID = spawn( foo
PID PID foo B A
PID
PID
foo
B
A

PID = spawn( foo ).

B! {self(), foo}.

receive {A, foo } -> fn_foo;

end.

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

Erlang - process spawning

Test (von Joe Armstrong)

Messe spawn-Zeit von Erlang Prozessen

Vereinfachung: Innerhalb EINER VM

von Erlang Prozessen Vereinfachung: Innerhalb EINER VM max(N) -> ! Max = erlang:system_info(process_limit),

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]).

Time2 * 1000 / N, ! io:format("Process spawn time=~p (~p) microseconds~n", [U1, U2]). Thursday, April 19,

erlang process timer

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

>> 100.000 Prozesse pro Sekunde

limitiert primär durch RAM der Erlang-VM

µsec (Realzeit) >> 100.000 Prozesse pro Sekunde limitiert primär durch RAM der Erlang-VM Thursday, April 19,

Erlang: Kernkonzepte

Funktionale Programmierung

Aktormodell

Leichtgewichtige Prozesse

“Hot Swapping”

Kernkonzepte Funktionale Programmierung Aktormodell Leichtgewichtige Prozesse “Hot Swapping” Thursday, April 19, 12

Erlang: Praxistauglichkeit

Erprobt

Server mit vielen parallelen Zugri en (Protokollserver, Datenbanken, …)

Systeme mit höchsten Verfügbarkeits- Anforderungen

en (Protokollserver, Datenbanken, …) Systeme mit höchsten Verfügbarkeits- Anforderungen 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

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/)

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

Erlang: Java-Idiome Immutability, Anonymous Inner Classes Active Objects Message Queues Thursday, April 19, 12

Node.js

Node.js 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

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

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

"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

}); }); 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);

le-server.js

' + filename); response.writeHead(404); response.end(); }); } }).listen(port); le-server.js Thursday, April 19, 12

Concurrency Level:

100

Time taken for tests:

6.000 seconds

Complete requests:

10000

Failed requests:

0

Write errors:

0

Keep-Alive requests:

0

Total transferred:

710781 bytes

HTML transferred:

150165 bytes

Requests per second:

1666.72 [#/sec] (mean)

Time per request:

59.998 [ms] (mean)

Time per request:

0.600 [ms] (mean, across all concurrent requests)

Transfer rate:

115.69 [Kbytes/sec] received

Connection Times (ms)

min mean[+/-sd] median

max

Connect:

0

8

8.3

5

57

Processing:

1

51

44.4

40

307

Waiting:

0

43

43.5

30

302

Total:

1

59

44.8

50

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)

73 90% 112 95% 174 98% 206 99% 224 100% 316 (longest request) Thursday, April 19,

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- le-server.js

} else { response.writeHead(404); response.end(); } }); }).listen(port); stream- le-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

}); 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

response); }); util.pump(request, remoteRequest); }).listen(port); proxy-pump.js Thursday, April 19, 12
Thursday, April 19, 12
Thursday, April 19, 12

Node.js: Kernkonzepte

Async I/O

Events & Callbacks

Single Process Model

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

Häu g: Vereinfachung

Node.js: Praxistauglichkeit Sehr jung, aber sehr aktiv Web 2.0-Umfeld Häu g: 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

Grizzly (http://grizzly.java.net/) Vert.x (https://github.com/purplefox/vert.x) Project Nashorn Thursday, April 19, 12

Fazit

Fazit Thursday, April 19, 12

1.

Es gibt ein Leben jenseits von Java

1. Es gibt ein Leben jenseits von Java Thursday, April 19, 12

2.

Alternativen können in der Praxis sinnvoll sein

2. Alternativen können in der Praxis sinnvoll sein Thursday, April 19, 12

3.

Die Beschä igung lohnt – auch 100%-Java-Entwickler

3. Die Beschä igung lohnt – auch 100%-Java-Entwickler Thursday, April 19, 12

Q&A

Q&A Thursday, April 19, 12

Q&A

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

© 2012 innoQ Deutschland GmbH Thursday, April 19, 12

Stefan Tilkov stefan.tilkov@innoq.com @stilkov

April 19, 12 Stefan Tilkov stefan.tilkov@innoq.com @stilkov innoQ Deutschland GmbH Krischerstr. 100 40789 Monheim am
April 19, 12 Stefan Tilkov stefan.tilkov@innoq.com @stilkov innoQ Deutschland GmbH Krischerstr. 100 40789 Monheim am
April 19, 12 Stefan Tilkov stefan.tilkov@innoq.com @stilkov innoQ Deutschland GmbH Krischerstr. 100 40789 Monheim am
April 19, 12 Stefan Tilkov stefan.tilkov@innoq.com @stilkov innoQ Deutschland GmbH Krischerstr. 100 40789 Monheim am

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

http://www.innoq.com innoQ Schweiz GmbH Gewerbestr. 11 CH-6330 Cham Switzerland Phone: +41 41 743 0116 info@innoq.com
http://www.innoq.com innoQ Schweiz GmbH Gewerbestr. 11 CH-6330 Cham Switzerland Phone: +41 41 743 0116 info@innoq.com