ERLANG: weitere Aspekte

Werbung
ERLANG (cont.)
Funktionale Programmierung
ERLANG: weitere Aspekte
D. Rösner
Institut für Wissens- und Sprachverarbeitung
Fakultät für Informatik
Otto-von-Guericke Universität Magdeburg
c
Sommer 2015, 10. April 2015, 2011–15
D.Rösner
D. Rösner FP 2015 . . .
1
ERLANG (cont.)
Gliederung
1
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
D. Rösner FP 2015 . . .
2
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Atome in ERLANG
Atome . . . konstante Literale, die für sich selbst stehen
([CT09], p.19)
syntaktische Konventionen:
Atome starten mit einem Kleinbuchstaben oder
sind in einfache Quotierungszeichen eingeschlossen
Beispiele:
person, einAtom, . . .
’Atom mit Blanks’, ’[email protected]’, . . .
D. Rösner FP 2015 . . .
4
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Atome in ERLANG
einzige Operation auf Atomen: Vergleiche
Beispiele:
90> alpha < omega.
true
91> alpha =< omega.
true
92> alpha >= omega.
false
D. Rösner FP 2015 . . .
5
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Strings in ERLANG
Zeichen werden in ERLANG als Integer dargestellt, Strings
als Listen von Zeichen (d.h. Integer)
93> [65,66,67].
"ABC"
94> $A.
65
95> $a.
97
$ . . . liefert ganzzahligen Wert zu einem Zeichen
D. Rösner FP 2015 . . .
7
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Strings in ERLANG
Beachte:
103> [49,50,51].
"123"
104> $1.
49
105> "123" == 123.
false
vordefinierte Konversionsfunktionen (BIF):
106> list_to_integer("123").
123
107> list_to_integer("123") == 123.
true
109> integer_to_list(4711).
"4711"
D. Rösner FP 2015 . . .
8
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Pattern matching in ERLANG
Pattern matching in ERLANG ist von Prolog inspiriert
im Unterschied zu Haskell dürfen auch im Pattern Variable
mehrfach vorkommen
daher muss in solchen Fällen die Gleichheit der Werte
nicht durch zusätzliche ‘guards’ geprüft werden
D. Rösner FP 2015 . . .
10
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Pattern matching in Haskell
allEqual :: Eq a => [a] -> Bool
allEqual [] = True
allEqual [_] = True
allEqual (el1:el2:rest) =
if el1 == el2 then allEqual (el2:rest)
else False
D. Rösner FP 2015 . . .
11
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Pattern matching in Erlang
-module(allequal).
-export([allequal/1]).
allequal([]) -> true;
allequal([_]) -> true;
allequal([X,X|T]) -> allequal([X|T]);
allequal([_,_|_]) -> false.
D. Rösner FP 2015 . . .
12
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Pattern matching in Erlang
-module(interval).
-export([interval/2]).
%interval(Low,High) when Low == High -> [High];
%% this guard can be captured in the pattern
interval(High,High) -> [High];
interval(Low,High) when Low < High
-> [Low] ++ interval(Low+1,High);
interval(_,_) -> [].
D. Rösner FP 2015 . . .
13
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Vergleich zwischen Erlang, Prolog und Haskell
Aneinanderfügen zweier Listen als Relation in Prolog bzw. als
Funktion in Erlang bzw. Haskell als Beispiel
Bemerkungen:
in allen Sprachen vordefiniert
Haskell: ++ . . . Infix-Operator
Erlang: ++ . . . Infix-Operator
Prolog: append/3
D. Rösner FP 2015 . . .
15
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Funktion append in Haskell
append :: [a] -> [a] -> [a]
append [] ys = ys
append (x:xs) ys = x:(append xs ys)
Bemerkungen:
strenge Typisierung
Polymorphie
D. Rösner FP 2015 . . .
16
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Funktion append in Erlang
-module(append).
-export([append/2]).
append([],Y) -> Y;
append([X|T],Y) -> [X|append(T,Y)].
D. Rösner FP 2015 . . .
17
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Relation append in Prolog
append([],Y,Y).
append([X|T],Y,[X|R]) :- append(T,Y,R).
Bemerkungen:
in unterschiedlicher Weise verwendbar
D. Rösner FP 2015 . . .
18
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Unendliche Listen
da in Haskell grundsätzlich ‘lazy’ evaluiert wird, werden für
unendliche Listen in Haskell keine zusätzlichen Sprachmittel
benötigt
Beispiel:
fibgen a b = a:(fibgen b (a + b))
fibs = fibgen 0 1
Main> take 10 fibs
[0,1,1,2,3,5,8,13,21,34]
D. Rösner FP 2015 . . .
20
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Unendliche Listen
in Scheme werden gewöhnliche Listen – und andere
Datenstrukturen – strikt (oder ’eager’) ausgewertet
mit cons-stream können sog. Ströme gebildet werden
D. Rösner FP 2015 . . .
21
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Ströme: Sprachmittel in SCHEME
Konstruktor: cons-stream
Selektoren: head, tail
Beziehung: für bel. a,b und x:
Wenn x ist (cons-stream a b), dann (head x) ist a
und (tail x) ist b.
Konstante: the-empty-stream
Prädikat: empty-stream?
D. Rösner FP 2015 . . .
22
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Ströme: Implementation
Implementation von Strömen durch verzögerte Evaluation
(delayed evaluation, lazy evaluation)
in normalen Listen: car und cdr werden zur
Konstruktionszeit evaluiert
in Strömen: tail erst zur Zugriffszeit evaluieren
(call-by-need)
Spezialform delay:
(delay <exp>) . . . liefert ein verzögertes Objekt, sog.
promise, dass erst mit force zur Ausführung veranlasst
wird
(force <promise>) . . . veranlasst Ausführung von
<promise>
D. Rösner FP 2015 . . .
23
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Implementation cont.
(cons-stream <a><b>) . . . Spezialform, die
gleichwertig mit
(cons <a> (delay <b>))
d.h. Strom wird als Paar dargestellt
im cdr steht promise zur Berechnung des tail
(define (head stream) (car stream))
(define (tail stream) (force (cdr stream)))
D. Rösner FP 2015 . . .
24
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Unendlich lange Ströme
Strom positiver ganzer Zahlen
(define (integers-starting-from n)
(cons-stream n (integers-starting-from (1+ n))))
(define integers (integers-starting-from 1))
Strom von Fibonacci-Zahlen
(define (fibgen a b)
(cons-stream a (fibgen b (+ a b))))
(define fibs (fibgen 0 1))
D. Rösner FP 2015 . . .
25
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Unendlich lange Ströme cont.
Sieb des Eratosthenes
(define (sieve stream)
(cons-stream
(head stream)
(sieve
(filter
(lambda (x) (not (divisible? x (head stream))))
(tail stream)))))
(define primes (sieve (integers-starting-from 2)))
D. Rösner FP 2015 . . .
26
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Unendliche Listen in Erlang
mit ‘lazy embedding’ lassen sich in Erlang unendliche
Listen kreieren
Variante 1:
-module(lazy).
-export([ints_from/1,take/2, add/2]).
ints_from(N) ->
fun() ->
[N|ints_from(N+1)]
end.
...
D. Rösner FP 2015 . . .
27
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Unendliche Listen in Erlang
Variante 1: cont.
...
take(N,Lazy) ->
if
N == 0 -> [];
true -> [hd(Lazy()) | take(N-1,tl(Lazy()))]
end.
%% analog zu add-stream in Scheme
add([], _) -> [];
add(_,[]) -> [];
add(Lazy1, Lazy2) ->
fun() ->
[hd(Lazy1()) + hd(Lazy2()) |
add(tl(Lazy1()), tl(Lazy2()))]
end.
D. Rösner FP 2015 . . .
28
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Unendliche Listen in Erlang
1> c("C:/Daten/roesner/erlang/modules/lazy.erl").
{ok,lazy}
2> CC = lazy:add(lazy:ints_from(97),lazy:ints_from(1)).
#Fun<lazy.1.109043180>
6> lazy:take(2,CC).
"bd"
D. Rösner FP 2015 . . .
29
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Unendliche Listen in Erlang
8> CC.
#Fun<lazy.1.109043180>
9> CC().
[98|#Fun<lazy.1.109043180>]
10> tl(CC()).
#Fun<lazy.1.109043180>
D. Rösner FP 2015 . . .
30
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Unendliche Listen in Erlang
11> (tl(CC()))().
[100|#Fun<lazy.1.109043180>]
Variante:
11> apply(tl(CC()),[]).
[100|#Fun<lazy.1.109043180>]
D. Rösner FP 2015 . . .
31
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Unendliche Listen in Erlang
Variante des ‘lazy embedding’ für unendliche Listen
-module(lazy2).
-export([ints_from/1, take/2, drop/2, add/2,
fibgen/2, nth/2, map/2, filter/2]).
ints_from(N) -> [N|fun() -> ints_from(N+1) end].
...
verzögert wird hier also nur der Listenrest
Analogie zu cons-stream in Scheme
D. Rösner FP 2015 . . .
32
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Unendliche Listen in Erlang
Variante des ‘lazy embedding’ für unendliche Listen
...
% trafo: hd(Lazy()) -> hd(Lazy)
%
tl(Lazy()) -> apply(tl(Lazy),[])
take(N,Lazy) ->
if
N == 0 -> [];
true -> [hd(Lazy) | take(N-1,apply(tl(Lazy),[]))]
end.
drop(N,Lazy) ->
if
N == 0 -> Lazy;
true -> drop(N-1,apply(tl(Lazy),[]))
end.
...
D. Rösner FP 2015 . . .
33
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Unendliche Listen in Erlang
Variante des ‘lazy embedding’ für unendliche Listen
...
add([], _) -> [];
add(_,[]) -> [];
add(Lazy1, Lazy2) ->
[hd(Lazy1) + hd(Lazy2)
| fun() -> add(apply(tl(Lazy1),[]),apply(tl(Lazy2),[]) ) end].
D. Rösner FP 2015 . . .
34
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Unendliche Listen in Erlang
Variante bei Implementierung des ‘lazy embedding’ für
unendliche Listen
% variant implementations of code from lazy2.erl
ints_from(N) -> [N|fun() -> ints_from(N+1) end].
% trafo: from lazy.erl to lazy2.erl
%
%
hd(Lazy()) -> hd(Lazy)
%
tl(Lazy()) -> apply(tl(Lazy),[])
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% additional: local var Cont for tl(Lazy), then Cont()
take(N,Lazy) ->
Cont = tl(Lazy),
if
N == 0 -> [];
true -> [hd(Lazy) | take(N-1,Cont())]
end.
...
D. Rösner FP 2015 . . .
35
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Unendliche Listen in Erlang
Variante bei Implementierung des ‘lazy embedding’ für
unendliche Listen
...
% possibility: exploit pattern matching
add([], _) -> [];
add(_,[]) -> [];
add([H1|TL1], [H2|TL2]) ->
[H1 + H2 | fun() -> add(TL1(), TL2()) end].
nth(N, [H | LTail]) ->
if
N == 1 -> H;
true -> nth(N-1, LTail())
end.
map(F,[H | LTail]) -> [F(H) | fun() -> map(F, LTail()) end].
...
D. Rösner FP 2015 . . .
36
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Literatur: I
Joe Armstrong.
Programming Erlang – Software for a Concurrent World.
The Pragmatic Bookshelf, Raleigh, North Carolina; Dallas,
Texas, 2007.
ISBN 1-9343560-0.
Joe Armstrong, Robert Virding, Claes Wikström, and Mike
Williams.
Concurrent Programming in ERLANG – Second Edition.
Pearson Education Ltd., Harlow, Essex GB, 1996.
ISBN 0-13-508301-X; A preprint of Part I is available for
download from
http://www.erlang.org/download/erlang-book-part1.pdf.
D. Rösner FP 2015 . . .
37
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Literatur: II
Francesco Cesarini and Simon Thompson.
Erlang Programming – A Concurrent Approach to Software
Development.
O’Reilly Media, Inc., Sebastopol, CA, USA, 2009.
ISBN 978-0-596-51818-91.
D. Rösner FP 2015 . . .
38
Herunterladen