Programmierparadigmen - Einführung in Scheme

Werbung
Funktionales Programmieren
Programmierparadigmen
Einführung in Scheme
D. Rösner
Institut für Wissens- und Sprachverarbeitung
Fakultät für Informatik
Otto-von-Guericke Universität Magdeburg
c
Sommer 2009, 31. März 2009, 2009
D.Rösner
D. Rösner PGP 2009 . . .
1
Funktionales Programmieren
Gliederung
1
Funktionales Programmieren
Scheme
Einführung
Scheme vs. Haskell
Programm-Daten-Äquivalenz
Funktionen höherer Ordnung
Skopus
Beispiel: Newton-Verfahren
D. Rösner PGP 2009 . . .
2
Funktionales Programmieren
Scheme
Scheme als funktionale Sprache:
Diskussion von Scheme im Vergleich mit Haskell
m.a.W. Gemeinsamkeiten und Unterschiede
Haskell als ‘Blaupause’ für funktionale Sprachen
Grundlegendes:
Interpreter
Definition von Werten mit define
(define <name> <wert>)
D. Rösner PGP 2009 . . .
4
Funktionales Programmieren
Scheme
Scheme als funktionale Sprache:
Funktionen sind Objekte erster Ordnung
eine Interaktion:
1 ]=> (define pi 3.1415)
;Value: pi
1 ]=> pi
;Value: 3.1415
1 ]=> (define quadriere
(lambda (zahl) (* zahl zahl)))
;Value: quadriere
1 ]=> (quadriere pi)
;Value: 9.86902225
D. Rösner PGP 2009 . . .
5
Funktionales Programmieren
Scheme
Scheme: Anonyme Funktionen
Syntax:
(lambda <parameterliste> <koerper>)
überall dort verwendbar, wo auch mit Symbol auf Funktion
verwiesen werden kann
1 ]=> ((lambda (n) (* n n)) 3)
;Value: 9
D. Rösner PGP 2009 . . .
6
Funktionales Programmieren
Scheme
Scheme: Anonyme Funktionen
alternative Syntax für benannte Funktionen
(define (<name> <par-1> ... <par-n>) <koerper>)
statt
(define <name>
(lambda (<par-1> ... <par-n>) <koerper>))
D. Rösner PGP 2009 . . .
7
Funktionales Programmieren
Scheme
Scheme: Übersicht
vordefinierte Datentypen
Zahlen: ganze, rationale, Fliesskomma, ...
Strings
Zeichen
boolesche Werte: #t, #f
wichtigster aggregierter Datentyp: Liste
Konstruktor: cons
Selektoren: car, cdr
Prädikate: null?
wichtige Kontrollstrukturen:
if
cond
Funktionen zur Konversion zwischen verschiedenen Typen
D. Rösner PGP 2009 . . .
8
Funktionales Programmieren
Scheme
Scheme vs. Haskell
Syntax:
in Scheme: Klammerung innerhalb geschachtelter
Ausdrücke
in Haskell: Vorrangregeln, Layoutregel
Typisierung?
in Scheme: keine Typisierung;
in Haskell: strenge Typisierung
Striktheit?
Scheme: strikt
Haskell: non-strikt
D. Rösner PGP 2009 . . .
9
Funktionales Programmieren
Scheme
Striktheit vs. Non-Striktheit
Eine (seiteneffekt-freie) Funktion heisst strikt, wenn
gefordert wird, dass alle ihre Argumente definiert sind und
so die Evaluationsordnung das Ergebnis nicht verändert.
Eine Funktion heisst non-strikt, wenn für sie die Forderung
nach Striktheit nicht erhoben wird.
Eine Sprache heisst strikt, wenn gefordert wird, dass alle
ihre Funktionen strikt.
Eine Sprache heisst non-strikt, wenn sie die Definition
non-strikter Funktionen zulässt.
D. Rösner PGP 2009 . . .
10
Funktionales Programmieren
Scheme
Scheme vs. Haskell
Art der Auswertung?
in Haskell: verzögerte Auswertung (lazy evaluation) für alle
Argumente
in Scheme: Auswertung für alle Argumente; aber:
verzögerte Auswertung und call-by-need möglich mit
delay und force
in Scheme nicht vordefiniert vorhanden sind u.a.
Listenkomprehension und Fallunterscheidung durch
Pattern Matching
D. Rösner PGP 2009 . . .
11
Funktionales Programmieren
Scheme
Scheme: Programm-Daten-Äquivalenz
Programme haben die Form von Listen
Scheme (und Lisp) sind homoikonisch, d.h.
selbstrepräsentierend
Programme können mit allen Listenfunktionen bearbeitet
werden
Beispiel:
(define compose
(lambda (f g)
(lambda (x) (f (g x)))))
1 ]=> ((compose car cdr) ’(1 2 3))
;Value: 2
D. Rösner PGP 2009 . . .
12
Funktionales Programmieren
Scheme
Scheme: Programm-Daten-Äquivalenz
Beispiel cont.:
(define compose2
(lambda (f g)
(eval (list ’lambda ’(x) (list f (list g ’x)))
(scheme-report-environment 5))))
1 ]=> ((compose2 car cdr) ’(1 2 3))
;Value: 2
}
D. Rösner PGP 2009 . . .
13
Funktionales Programmieren
Scheme
Scheme: weitere Aspekte
Funktionen mit beliebiger Anzahl von Argumenten möglich
(sog. Restparameter, der an Liste gebunden)
Beispiel:
(define (avg . nums) (average nums))
average erwartet Liste als Argument
Definition:
(define (average nums)
(/ (apply + nums) (length nums)))
D. Rösner PGP 2009 . . .
14
Funktionales Programmieren
Scheme
Scheme: Funktionen höherer Ordnung
z.B. Falten einer zweistelligen Funktion in eine Liste:
(define fold
(lambda (f l i)
(if (null? l) i ;; identity for f
(f (car l) (fold f (cdr l) i)))))
D. Rösner PGP 2009 . . .
15
Funktionales Programmieren
Scheme
Scheme: Funktionen höherer Ordnung
partielle Anwendungen sind bei Funktionen im
Curry-Format möglich
(define curry
(lambda (f) (lambda (a) (lambda (b) (f a b)))))
1 ]=> (((curry +) 3) 4)
;Value: 7
(define curried-plus (curry +))
D. Rösner PGP 2009 . . .
16
Funktionales Programmieren
Scheme
Scheme vs. Haskell:
Sichtbarkeit von Definitionen
die Definitionen auf dem Toplevel von Scheme sind ‘global’
sichtbar
wechselseitige Bezugnahme in rekursiven Definitionen ist
möglich
Beispiel:
1 ]=> (define (isOdd n)
(if (<= n 0) () (isEven (- n 1))))
;Value: isodd
...
D. Rösner PGP 2009 . . .
17
Funktionales Programmieren
Scheme
Scheme vs. Haskell: Sichtbarkeit von Definitionen
Beispiel cont.:
1 ]=> (define (isEven n)
(if (< n 0) ()
(if (= n 0) #t (isOdd (- n 1)))))
;Value: iseven
1 ]=> (isEven 5)
;Value: ()
1 ]=> (isOdd 5)
;Value: #t
D. Rösner PGP 2009 . . .
18
Funktionales Programmieren
Scheme
Lokale Definitionen
Motivation:
Vermeiden wiederholter Berechnungen
klarer strukturierter Code
Beispiel:
eine Funktion addPairwise’, die korrespondierende
Elemente zweier Zahlenlisten addiert und – falls eine Liste
keine Elemente mehr hat – den aktuellen Rest der anderen
an die Liste der Paarsummen anhängt
D. Rösner PGP 2009 . . .
19
Funktionales Programmieren
Scheme
Scheme: lokale Bindungen mit let und let*
Syntax:
(let ((var1 val1)
(var2 val2)
... (varN valN))
<body>)
Semantik:
bei der Auswertung von <body> sind die in var1, var2,
..., varN gebundenen Werte val1, val2, ...,
valN verfügbar
D. Rösner PGP 2009 . . .
20
Funktionales Programmieren
Scheme
Scheme: lokale Bindungen mit let und let*
Beispiel: addPairwiseRest als Äquivalent zu
addPairwise’
(define (addPairwiseRest list1 list2)
(let ((front (addPairwise list1 list2))
(minLength (min (length list1)(length list2))))
(let ((rear (append (drop minLength list1)
(drop minLength list2))))
(append front rear))))
D. Rösner PGP 2009 . . .
21
Funktionales Programmieren
Scheme
Scheme: lokale Bindungen mit let und let*
Beachte: bei let erfolgt die Auswertung und Bindung in
den einzelnen (var1 val1) (var2 val2) ...
(varN valN) parallel
daher folgendes falsch:
(define (addPairwiseRest list1 list2)
(let ((front (addPairwise list1 list2))
(minLength (min (length list1)(length list2)))
(rear (append (drop minLength list1)
(drop minLength list2))))
(append front rear)))
1 ]=> (addPairwiseRest ’(4 7 1 1 ) ’(8 15))
;Unbound variable: minlength
D. Rösner PGP 2009 . . .
22
Funktionales Programmieren
Scheme
Scheme: lokale Bindungen mit let und let*
let* ist wie let, nur erfolgt Auswertung und Bindung in
den einzelnen (var1 val1) (var2 val2) ...
(varN valN) sequentiell
m.a.W. für die Ausdrücke vali (für 2 <= i <= n) stehen
die Bindungen var1, var2, ..., var(i-1) zur
Verfügung
D. Rösner PGP 2009 . . .
23
Funktionales Programmieren
Scheme
Scheme: lokale Bindungen mit let und let*
Beispiel für let*:
(define (addPairwiseRest list1 list2)
(let* ((front (addPairwise list1 list2))
(minLength (min (length list1)(length list2)))
(rear (append (drop minLength list1)
(drop minLength list2))))
(append front rear)))
1 ]=> (addPairwiseRest ’(4 7 1 1 ) ’(8 15))
;Value 12: (12 22 1 1)
D. Rösner PGP 2009 . . .
24
Funktionales Programmieren
Scheme
Beispiel cont.
Hilfsfunktionen a la Haskell:
(define (addPairwise list1 list2)
(if (or (null? list1)(null? list2))
()
(cons (+ (car list1)(car list2))
(addPairwise (cdr list1)(cdr list2)))))
(define (take n list)
(if (= n 0) ()
(cons (car list) (take (- n 1) (cdr list)))))
(define (drop n list)
(if (= n 0) list
(drop (- n 1) (cdr list))))
D. Rösner PGP 2009 . . .
25
Funktionales Programmieren
Scheme
Scheme: Berechnung Quadratwurzel mit
Newton-Verfahren
(define (sqrt x)
(sqrt-iter 1 x))
(define (sqrt-iter guess x)
(if (good-enough? guess x)
guess
(sqrt-iter (improve guess x) x)))
(define (good-enough? guess x)
(< (abs (- (square guess) x)) .001))
(define (improve guess x)
(average guess (/ x guess)))
D. Rösner PGP 2009 . . .
26
Funktionales Programmieren
Scheme
Blockstruktur:
(define (sqrt x)
(define (good-enough? guess x)
(< (abs (- (square guess) x)) .001))
(define (improve guess x)
(average guess (/ x guess)))
(define (sqrt-iter guess x)
(if (good-enough? guess x)
guess
(sqrt-iter (improve guess x) x)))
(sqrt-iter 1 x)
)
D. Rösner PGP 2009 . . .
27
Funktionales Programmieren
Scheme
Interne Definitionen
Ausnutzen, daß x in sqrt gebunden (lexikalischer Skopus):
(define (sqrt x)
(define (good-enough? guess)
(< (abs (- (square guess) x)) .001))
(define (improve guess)
(average guess (/ x guess)))
(define (sqrt-iter guess)
(if (good-enough? guess)
guess
(sqrt-iter (improve guess))))
(sqrt-iter 1))
D. Rösner PGP 2009 . . .
28
Funktionales Programmieren
Scheme
lexikalischer Skopus:
freie Variable in einer Prozedur verweisen auf Variable in
umfassenden Prozeduren
m.a.W.: Werte freier Variable werden in der Umgebung
gesucht, in der die Prozedur definiert wurde
D. Rösner PGP 2009 . . .
29
Funktionales Programmieren
Scheme
Literatur: I
Harold Abelson, G.J.Sussman, and J.Sussman.
Structure and Interpretation of Computer Programs.
MIT Press, Cambridge, MA, USA, 1996.
2nd edition; Bem.: dt. Übersetzung existiert, aber engl.
Original ist mehr zu empfehlen – DR.
Michael Lee Scott.
Programming Language Pragmatics.
Academic Press, San Diego, CA, USA, 2000.
ISBN 1-55860-578-9.
D. Rösner PGP 2009 . . .
30
Funktionales Programmieren
Scheme
Literatur: II
Ravi Sethi.
Programming Languages – Concepts and Constructs.
Addison-Wesley, Reading, Mass. USA, 1996.
ISBN 0-201-59065-4.
D. Rösner PGP 2009 . . .
31
Herunterladen