Funktionales Programmieren: Scheme Funktionales Programmieren: Scheme Gliederung Programmierparadigmen 1 Einführung in Scheme D. Rösner Institut für Wissens- und Sprachverarbeitung Fakultät für Informatik Otto-von-Guericke Universität Magdeburg Funktionales Programmieren: Scheme Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz c Sommer 2013, 17. Juni 2013, 2011 - 13 D.Rösner D. Rösner PGP 2013 . . . Funktionales Programmieren: Scheme 1 D. Rösner PGP 2013 . . . Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Funktionales Programmieren: Scheme Historie 2 Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Historie unterschiedliche Ausrichtungen: Fortran: numerische Berechnungen Frage: Welches sind die zwei ältesten und (in modernisierter Form) immer noch benutzten Programmiersprachen? Lisp: Symbolverarbeitung Symbolverarbeitung? Beispiele: ... ... symbolisches Rechnen (z.B. Differentiation, Integration) logisches Schliessen Analyse und Synthese chemischer Formeln Verarbeitung natürlicher Sprache Repräsentation von Wissen (z.B. semantische Netze) ... Frage: Wann wurden diese Sprachen entwickelt? ... D. Rösner PGP 2013 . . . 4 D. Rösner PGP 2013 . . . 5 Funktionales Programmieren: Scheme Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Funktionales Programmieren: Scheme Symbolverarbeitung mit Lisp Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Scheme als funktionale Sprache: Sprachmittel für Symbolverarbeitung in Lisp Diskussion von Scheme im Vergleich mit Haskell Atome als elementare Bausteine zusammengesetzte Strukturen auf der Basis verschachtelter Listen Beispiel: mögliche Darstellung eines Syntaxbaums (S (NP (DET Der) (N Mann)) (VP (V fragt) (PP (P nach) (NP (DET dem) (N Weg) (PP (P zum) (NP (N Bahnhof))))))) m.a.W. Gemeinsamkeiten und Unterschiede Haskell als ‘Blaupause’ für funktionale Sprachen Grundlegendes: Interpreter Definition von Assoziationen zwischen Namen und Werten mit define (define <name> <wert>) Scheme ist ein Dialekt von Lisp D. Rösner PGP 2013 . . . Funktionales Programmieren: Scheme D. Rösner PGP 2013 . . . 6 Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Funktionales Programmieren: Scheme Scheme als funktionale Sprache: 7 Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Scheme: Anonyme Funktionen wichtig: Funktionen sind Objekte erster Ordnung eine Interaktion: Syntax: (lambda <parameterliste> <koerper>) überall dort verwendbar, wo auch mit Symbol auf Funktion verwiesen werden kann 1 ]=> (define pi 3.1415) ;Value: pi 1 ]=> pi ;Value: 3.1415 1 ]=> ((lambda (n) (* n n)) 3) 1 ]=> (define quadriere (lambda (zahl) (* zahl zahl))) ;Value: quadriere ;Value: 9 1 ]=> (quadriere pi) ;Value: 9.86902225 D. Rösner PGP 2013 . . . 8 D. Rösner PGP 2013 . . . 9 Funktionales Programmieren: Scheme Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Funktionales Programmieren: Scheme Scheme: Anonyme Funktionen Scheme: Übersicht vordefinierte Datentypen alternative Syntax für benannte Funktionen Zahlen: ganze, rationale, Fliesskomma, ... Strings: z.B. "ein String" Zeichen: z.B. #\a #\Z #\* #\space boolesche Werte: #t, #f ... (define (<name> <par-1> ... <par-n>) <koerper>) statt (define <name> (lambda (<par-1> ... <par-n>) <koerper>)) D. Rösner PGP 2013 . . . Funktionales Programmieren: Scheme Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz 10 Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz D. Rösner PGP 2013 . . . Funktionales Programmieren: Scheme Scheme: Übersicht 11 Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Scheme vs. Haskell Syntax: wichtigster aggregierter Datentyp: Liste in Scheme: Klammerung innerhalb geschachtelter Ausdrücke in Haskell: Vorrangregeln, Layoutregel Konstruktor: cons Selektoren: car, cdr Prädikate: list?, null? Typisierung? wichtige Kontrollstrukturen: in Scheme: keine Typisierung; in Haskell: strenge Typisierung if cond Striktheit? Scheme: strikt Haskell: non-strikt Funktionen zur Konversion zwischen verschiedenen Typen, z.B. rein funktional (pur)? number->string string->list ... D. Rösner PGP 2013 . . . Scheme: nicht pur, Seiteneffekte möglich z.B. mit set! Haskell: pur 12 D. Rösner PGP 2013 . . . 14 Funktionales Programmieren: Scheme Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Funktionales Programmieren: Scheme Scheme vs. Haskell Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz 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. in Scheme: keine Typisierung Typüberprüfung durch vor- oder eigendefinierte Typprädikate Beispiele: 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. number? list? string? ... Eine Sprache heisst non-strikt, wenn sie die Definition non-strikter Funktionen zulässt. s.a. [Sco00], Ch. 11.2.2. D. Rösner PGP 2013 . . . Funktionales Programmieren: Scheme 15 Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz D. Rösner PGP 2013 . . . Funktionales Programmieren: Scheme Scheme vs. Haskell 16 Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Scheme: weitere Aspekte Art der Auswertung? Funktionen mit beliebiger Anzahl von Argumenten möglich (sog. Restparameter, der an Liste gebunden) Beispiel: 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 s.a. [Sco00], Ch. 11.2.2. (define (avg . nums) (average nums)) average erwartet Liste als Argument Definition: in Scheme nicht vordefiniert vorhanden sind u.a. (define (average nums) (/ (apply + nums) (length nums))) Listenkomprehensionen und Fallunterscheidung durch Pattern Matching D. Rösner PGP 2013 . . . 17 D. Rösner PGP 2013 . . . 18 Funktionales Programmieren: Scheme Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Funktionales Programmieren: Scheme Scheme: Funktionen höherer Ordnung Scheme: Funktionen höherer Ordnung map . . . Anwenden einer Funktion auf die Elemente einer Liste und Rückgabe der Liste der Ergebnisse z.B. Falten einer zweistelligen Funktion in eine Liste: > (define (map f l) (if (null? l) ’() (cons (f (car l)) (map f (cdr l))))) (define fold (lambda (f l i) (if (null? l) i ;; identity for f (f (car l) (fold f (cdr l) i))))) > (map (lambda (x) (* x x)) ’(2 3 4 5)) (4 9 16 25) D. Rösner PGP 2013 . . . Funktionales Programmieren: Scheme 20 Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz D. Rösner PGP 2013 . . . Funktionales Programmieren: Scheme Scheme: Funktionen höherer Ordnung 21 Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Scheme vs. Haskell: partielle Anwendungen sind bei Funktionen im Curry-Format möglich 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)))) (define curry (lambda (f) (lambda (a) (lambda (b) (f a b))))) 1 ]=> (((curry +) 3) 4) ;Value: 7 ;Value: isodd ... (define curried-plus (curry +)) D. Rösner PGP 2013 . . . Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz 22 D. Rösner PGP 2013 . . . 24 Funktionales Programmieren: Scheme Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Funktionales Programmieren: Scheme Scheme vs. Haskell: Sichtbarkeit von Definitionen Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Lokale Definitionen Beispiel cont.: 1 ]=> (define (isEven n) (if (< n 0) () (if (= n 0) #t (isOdd (- n 1))))) 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 ;Value: iseven 1 ]=> (isEven 5) ;Value: () 1 ]=> (isOdd 5) ;Value: #t D. Rösner PGP 2013 . . . Funktionales Programmieren: Scheme 25 Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz D. Rösner PGP 2013 . . . Funktionales Programmieren: Scheme Scheme: lokale Bindungen mit let und let* 26 Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Scheme: lokale Bindungen mit let und let* Syntax: Beispiel: addPairwiseRest als Äquivalent zu addPairwise’ (let ((var1 val1) (var2 val2) ... (varN valN)) <body>) (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)))) Semantik: bei der Auswertung von <body> sind die in var1, var2, ..., varN gebundenen Werte val1, val2, ..., valN verfügbar D. Rösner PGP 2013 . . . 27 D. Rösner PGP 2013 . . . 28 Funktionales Programmieren: Scheme Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Funktionales Programmieren: Scheme Scheme: lokale Bindungen mit let und let* Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz 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: let* ist wie let, nur erfolgt Auswertung und Bindung in den einzelnen (var1 val1) (var2 val2) ... (varN valN) sequentiell (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))) 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 1 ]=> (addPairwiseRest ’(4 7 1 1 ) ’(8 15)) ;Unbound variable: minlength D. Rösner PGP 2013 . . . Funktionales Programmieren: Scheme 29 Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz D. Rösner PGP 2013 . . . Funktionales Programmieren: Scheme Scheme: lokale Bindungen mit let und let* 30 Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz 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))))) 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))) (define (take n list) (if (= n 0) () (cons (car list) (take (- n 1) (cdr list))))) 1 ]=> (addPairwiseRest ’(4 7 1 1 ) ’(8 15)) ;Value 12: (12 22 1 1) D. Rösner PGP 2013 . . . (define (drop n list) (if (= n 0) list (drop (- n 1) (cdr list)))) 31 D. Rösner PGP 2013 . . . 32 Funktionales Programmieren: Scheme Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Funktionales Programmieren: Scheme Scheme: Berechnung Quadratwurzel mit Newton-Verfahren Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz 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))) (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)) (sqrt-iter 1 x) ) (define (improve guess x) (average guess (/ x guess))) D. Rösner PGP 2013 . . . Funktionales Programmieren: Scheme 34 Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz D. Rösner PGP 2013 . . . Funktionales Programmieren: Scheme Interne Definitionen 35 Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz lexikalischer Skopus: 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)))) 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 (sqrt-iter 1)) D. Rösner PGP 2013 . . . 36 D. Rösner PGP 2013 . . . 37 Funktionales Programmieren: Scheme Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Funktionales Programmieren: Scheme Symbolisches Differenzieren Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Symbolisches Differenzieren zentrale Funktion: deriv (s.a. [AGJ96]) (define (deriv exp var) (cond ((constant? exp) 0) ((variable? exp) (if (same-variable? exp var) 1 0)) ((sum? exp) (make-sum (deriv (addend exp) var) (deriv (augend exp) var))) ((product? exp) (make-sum (make-product (multiplier exp) (deriv (multiplicand exp) var)) (make-product (deriv (multiplier exp) var) D. Rösner PGP 2013 . . . 39 (multiplicand exp)))))) Funktionales Programmieren: Scheme Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Darstellung von Summen (s.a. [AGJ96]) (define (make-sum a1 a2) (list ’+ a1 a2)) (define (sum? x) (if (not (atom? x)) (eq? (car x) ’+) nil)) (define (addend s) (cadr s)) (define (augend s) (caddr s)) D. Rösner PGP 2013 . . . Funktionales Programmieren: Scheme Symbolisches Differenzieren 40 Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Symbolisches Differenzieren Darstellung von Produkten (s.a. [AGJ96]) allgemein: Darstellung von Datenstrukturen (define (make-product m1 m2) (list ’* m1 m2)) Konstruktoren Prädikate Selektoren (define (product? x) (if (not (atom? x)) (eq? (car x) ’*) nil)) s.a. [AGJ96] (define (multiplier p) (cadr p)) (define (multiplicand p) (caddr p)) D. Rösner PGP 2013 . . . 41 D. Rösner PGP 2013 . . . 42 Funktionales Programmieren: Scheme Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Funktionales Programmieren: Scheme Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Symbolisches Differenzieren Symbolisches Differenzieren Hilfsfunktionen (s.a. [AGJ96]) Hilfsfunktionen (s.a. [AGJ96]) (define (constant? x) (number? x)) (define (atom? x) (or (number? x) (string? x) (symbol? x) (null? x) (eq? x #t))) (define (variable? x) (symbol? x)) (define (same-variable? v1 v2) (and (variable? v1) (variable? v2) (eq? v1 v2))) D. Rösner PGP 2013 . . . Funktionales Programmieren: Scheme 43 Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz D. Rösner PGP 2013 . . . Funktionales Programmieren: Scheme Symbolisches Differenzieren 44 Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Symbolisches Differenzieren Beispiele (s.a. [AGJ96]) verbesserte Konstruktor-Funktionen (s.a. [AGJ96]) Welcome to DrRacket, version 5.3.4 [3m]. Language: R5RS [custom]; memory limit: 128 MB. > (deriv ’(+ x 3) ’x) (define (make-sum a1 a2) (cond ((and (number? a1) (number? a2)) (+ a1 a2)) ((number? a1) (if (= a1 0) a2 (list ’+ a1 a2))) ((number? a2) (if (= a2 0) a1 (list ’+ a1 a2))) (else (list ’+ a1 a2)))) (+ 1 0) > (deriv ’(* x y) ’y) (+ (* x 1) (* 0 y)) > (deriv ’(* (* x y) (+ x 3)) ’x) (+ (* (* x y) (+ 1 0)) (* (+ (* x 0) (* 1 y)) (+ x 3))) Welche Vereinfachungen von Termen? D. Rösner PGP 2013 . . . 45 D. Rösner PGP 2013 . . . 46 Funktionales Programmieren: Scheme Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Funktionales Programmieren: Scheme Symbolisches Differenzieren Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Symbolisches Differenzieren verbesserte Konstruktor-Funktionen (s.a. [AGJ96]) Anwendung verbesserter Konstruktor-Funktion make-sum (s.a. [AGJ96]) (define (make-product m1 m2) (cond ((and (number? m1) (number? m2)) (* m1 m2)) ((number? m1) (cond ((= m1 0) 0) ((= m1 1) m2) (else (list ’* m1 m2)))) ((number? m2) (cond ((= m2 0) 0) ((= m2 1) m1) (else (list ’* m1 m2)))) (else (list ’* m1 m2)))) > (deriv ’(+ x 3) ’x) 1 > (deriv ’(* (* x y) (+ x 3)) ’x) (+ (* (* x y) 1) (* (+ (* x 0) (* 1 y)) (+ x 3))) D. Rösner PGP 2013 . . . Funktionales Programmieren: Scheme 47 Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz D. Rösner PGP 2013 . . . Funktionales Programmieren: Scheme Symbolisches Differenzieren 48 Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Scheme: Programm-Daten-Äquivalenz Anwendung verbesserter Konstruktor-Funktion make-product (s.a. [AGJ96]) statt Programme haben die Form von Listen Scheme (und Lisp) sind homoikonisch, d.h. selbstrepräsentierend Programme können mit allen Listenfunktionen bearbeitet werden Beispiel: > (deriv ’(* (* x y) (+ x 3)) ’x) (+ (* (* x y) 1) (* (+ (* x 0) (* 1 y)) (+ x 3))) (define compose (lambda (f g) (lambda (x) (f (g x))))) jetzt > (deriv ’(* (* x y) (+ x 3)) ’x) (+ (* x y) (* y (+ x 3))) D. Rösner PGP 2013 . . . 1 ]=> ((compose car cdr) ’(1 2 3)) ;Value: 2 49 D. Rösner PGP 2013 . . . 51 Funktionales Programmieren: Scheme Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz Funktionales Programmieren: Scheme Scheme: Programm-Daten-Äquivalenz Literatur: I Beispiel cont.: 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. (define compose2 (lambda (f g) (eval (list ’lambda ’(x) (list f (list g ’x))) (scheme-report-environment 5)))) Michael Lee Scott. Programming Language Pragmatics. Academic Press, San Diego, CA, USA, 2000. ISBN 1-55860-578-9. 1 ]=> ((compose2 car cdr) ’(1 2 3)) ;Value: 2 D. Rösner PGP 2013 . . . Einführung Scheme vs. Haskell Funktionen höherer Ordnung Skopus Beispiel: Newton-Verfahren Beispiel: Symbolisches Differenzieren Programm-Daten-Äquivalenz 52 D. Rösner PGP 2013 . . . 53