Funktionale Programmierung

Werbung
ERLANG (cont.)
ERLANG (cont.)
Gliederung
Funktionale Programmierung
ERLANG: weitere Aspekte
1
D. Rösner
Institut für Wissens- und Sprachverarbeitung
Fakultät für Informatik
Otto-von-Guericke Universität Magdeburg
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
c
Sommer 2015, 10. April 2015, 2011–15
D.Rösner
D. Rösner FP 2015 . . .
ERLANG (cont.)
D. Rösner FP 2015 . . .
1
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
ERLANG (cont.)
Atome in ERLANG
2
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Atome in ERLANG
Atome . . . konstante Literale, die für sich selbst stehen
([CT09], p.19)
syntaktische Konventionen:
einzige Operation auf Atomen: Vergleiche
Beispiele:
90> alpha < omega.
true
91> alpha =< omega.
true
92> alpha >= omega.
false
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
D. Rösner FP 2015 . . .
5
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
ERLANG (cont.)
Strings in ERLANG
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Strings in ERLANG
Beachte:
103> [49,50,51].
"123"
104> $1.
49
105> "123" == 123.
false
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
vordefinierte Konversionsfunktionen (BIF):
106> list_to_integer("123").
123
107> list_to_integer("123") == 123.
true
$ . . . liefert ganzzahligen Wert zu einem Zeichen
109> integer_to_list(4711).
"4711"
D. Rösner FP 2015 . . .
ERLANG (cont.)
7
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
D. Rösner FP 2015 . . .
ERLANG (cont.)
Pattern matching in ERLANG
8
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Pattern matching in Haskell
allEqual :: Eq a => [a] -> Bool
Pattern matching in ERLANG ist von Prolog inspiriert
allEqual [] = True
im Unterschied zu Haskell dürfen auch im Pattern Variable
mehrfach vorkommen
allEqual [_] = True
daher muss in solchen Fällen die Gleichheit der Werte
nicht durch zusätzliche ‘guards’ geprüft werden
D. Rösner FP 2015 . . .
allEqual (el1:el2:rest) =
if el1 == el2 then allEqual (el2:rest)
else False
10
D. Rösner FP 2015 . . .
11
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
ERLANG (cont.)
Pattern matching in Erlang
Pattern matching in Erlang
-module(interval).
-export([interval/2]).
-module(allequal).
-export([allequal/1]).
%interval(Low,High) when Low == High -> [High];
%% this guard can be captured in the pattern
allequal([]) -> true;
allequal([_]) -> true;
allequal([X,X|T]) -> allequal([X|T]);
allequal([_,_|_]) -> false.
D. Rösner FP 2015 . . .
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
interval(High,High) -> [High];
interval(Low,High) when Low < High
-> [Low] ++ interval(Low+1,High);
interval(_,_) -> [].
12
D. Rösner FP 2015 . . .
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
ERLANG (cont.)
Vergleich zwischen Erlang, Prolog und Haskell
13
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Funktion append in Haskell
Aneinanderfügen zweier Listen als Relation in Prolog bzw. als
Funktion in Erlang bzw. Haskell als Beispiel
Bemerkungen:
append :: [a] -> [a] -> [a]
append [] ys = ys
in allen Sprachen vordefiniert
append (x:xs) ys = x:(append xs ys)
Haskell: ++ . . . Infix-Operator
Erlang: ++ . . . Infix-Operator
Prolog: append/3
Bemerkungen:
strenge Typisierung
Polymorphie
D. Rösner FP 2015 . . .
15
D. Rösner FP 2015 . . .
16
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
ERLANG (cont.)
Funktion append in Erlang
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Relation append in Prolog
-module(append).
-export([append/2]).
append([],Y,Y).
append([X|T],Y,[X|R]) :- append(T,Y,R).
append([],Y) -> Y;
append([X|T],Y) -> [X|append(T,Y)].
Bemerkungen:
in unterschiedlicher Weise verwendbar
D. Rösner FP 2015 . . .
ERLANG (cont.)
17
D. Rösner FP 2015 . . .
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
ERLANG (cont.)
Unendliche Listen
18
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:
in Scheme werden gewöhnliche Listen – und andere
Datenstrukturen – strikt (oder ’eager’) ausgewertet
mit cons-stream können sog. Ströme gebildet werden
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
D. Rösner FP 2015 . . .
21
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
ERLANG (cont.)
Ströme: Sprachmittel in SCHEME
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Ströme: Implementation
Implementation von Strömen durch verzögerte Evaluation
(delayed evaluation, lazy evaluation)
Konstruktor: cons-stream
in normalen Listen: car und cdr werden zur
Konstruktionszeit evaluiert
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.
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
Konstante: the-empty-stream
Prädikat: empty-stream?
(force <promise>) . . . veranlasst Ausführung von
<promise>
D. Rösner FP 2015 . . .
ERLANG (cont.)
22
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
D. Rösner FP 2015 . . .
ERLANG (cont.)
Implementation cont.
23
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Unendlich lange Ströme
Strom positiver ganzer Zahlen
(cons-stream <a><b>) . . . Spezialform, die
gleichwertig mit
(cons <a> (delay <b>))
(define (integers-starting-from n)
(cons-stream n (integers-starting-from (1+ n))))
(define integers (integers-starting-from 1))
d.h. Strom wird als Paar dargestellt
im cdr steht promise zur Berechnung des tail
Strom von Fibonacci-Zahlen
(define (head stream) (car stream))
(define (fibgen a b)
(cons-stream a (fibgen b (+ a b))))
(define (tail stream) (force (cdr stream)))
(define fibs (fibgen 0 1))
D. Rösner FP 2015 . . .
24
D. Rösner FP 2015 . . .
25
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
ERLANG (cont.)
Unendlich lange Ströme cont.
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Unendliche Listen in Erlang
Sieb des Eratosthenes
(define (sieve stream)
(cons-stream
(head stream)
(sieve
(filter
(lambda (x) (not (divisible? x (head stream))))
(tail stream)))))
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.
(define primes (sieve (integers-starting-from 2)))
...
D. Rösner FP 2015 . . .
ERLANG (cont.)
26
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
D. Rösner FP 2015 . . .
ERLANG (cont.)
Unendliche Listen in Erlang
27
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 . . .
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"
28
D. Rösner FP 2015 . . .
29
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
ERLANG (cont.)
Unendliche Listen in Erlang
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 . . .
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
11> (tl(CC()))().
[100|#Fun<lazy.1.109043180>]
Variante:
11> apply(tl(CC()),[]).
[100|#Fun<lazy.1.109043180>]
30
D. Rösner FP 2015 . . .
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
ERLANG (cont.)
Unendliche Listen in Erlang
31
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Unendliche Listen in Erlang
Variante des ‘lazy embedding’ für unendliche Listen
...
Variante des ‘lazy embedding’ für unendliche Listen
% trafo: hd(Lazy()) -> hd(Lazy)
%
tl(Lazy()) -> apply(tl(Lazy),[])
-module(lazy2).
-export([ints_from/1, take/2, drop/2, add/2,
fibgen/2, nth/2, map/2, filter/2]).
take(N,Lazy) ->
if
N == 0 -> [];
true -> [hd(Lazy) | take(N-1,apply(tl(Lazy),[]))]
end.
ints_from(N) -> [N|fun() -> ints_from(N+1) end].
...
verzögert wird hier also nur der Listenrest
drop(N,Lazy) ->
if
N == 0 -> Lazy;
true -> drop(N-1,apply(tl(Lazy),[]))
end.
...
Analogie zu cons-stream in Scheme
D. Rösner FP 2015 . . .
32
D. Rösner FP 2015 . . .
33
ERLANG (cont.)
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
ERLANG (cont.)
Unendliche Listen in Erlang
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
Variante des ‘lazy embedding’ für unendliche Listen
ints_from(N) -> [N|fun() -> ints_from(N+1) end].
...
add([], _) -> [];
add(_,[]) -> [];
add(Lazy1, Lazy2) ->
[hd(Lazy1) + hd(Lazy2)
| fun() -> add(apply(tl(Lazy1),[]),apply(tl(Lazy2),[]) ) end].
D. Rösner FP 2015 . . .
ERLANG (cont.)
34
% 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 . . .
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
ERLANG (cont.)
Unendliche Listen in Erlang
Atome
Strings
Pattern matching
Vergleich
Unendliche Listen
Literatur: I
Variante bei Implementierung des ‘lazy embedding’ für
unendliche Listen
Joe Armstrong.
Programming Erlang – Software for a Concurrent World.
The Pragmatic Bookshelf, Raleigh, North Carolina; Dallas,
Texas, 2007.
ISBN 1-9343560-0.
...
% possibility: exploit pattern matching
add([], _) -> [];
add(_,[]) -> [];
add([H1|TL1], [H2|TL2]) ->
[H1 + H2 | fun() -> add(TL1(), TL2()) end].
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.
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 . . .
35
36
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