Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

Programmierung 1 - Repetitorium WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner Homepage:

Ähnliche Präsentationen


Präsentation zum Thema: "Programmierung 1 - Repetitorium WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner Homepage:"—  Präsentation transkript:

1 Programmierung 1 - Repetitorium WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner Homepage:

2 Programmierung 1 - Repetitorium Mittwoch, den Kapitel 6 Konstruktortypen und Ausnahmen

3 Programmierung 1 - Repetitorium 6.1 Varianten und Konstruktoren Ziel: Darstellung der drei geometrischen Formen Kreis, Quadrat und Dreieck als mathematische Objekte Das Paar stellt einen Kreis mit Radius r dar. Das Paar stellt ein Quadrat mit der Seitenlänge a dar. Das Paar > stellt ein Dreieck mit den Seitenlängen a,b,c dar. Die erste Komponente des Paares bezeichnet man als Variantennummer. Sie gibt die Form des geometrischen Objekts an. Die zweite Komponente des Paares bezeichnet man als Datum. Sie spezifiziert die Dimensionen des geometrischen Objekts. datatype shape = Circle of real | Square of real | Triangle of real * real * real

4 Programmierung 1 - Repetitorium 6.1 Varianten und Konstruktoren Der Datentyp shape liefert uns jetzt die Konstruktoren Circle, Square und Triangle. Circle 4.0 Square 3.0 Triangle ( 4.0, 3.0, 5.0 ) Circle Square Triangle Berechnung des Flächeninhalts : fun area (Circle r) = Math.pi * r * r | area (Square a) = a * a | area (Triangle (a,b,c)) = let val s = (a+b+c)/2.0 in Math.sqrt(s*(s-a)*(s-b)*(s-c)) end

5 Programmierung 1 - Repetitorium 6.1 Varianten und Konstruktoren Die Prozedur area ist mit drei Regeln definiert, die jeweils für eine der drei Varianten von shape zuständig sind. Die Muster der Regeln haben die Form einer Konstruktoranwendung. Die Deklaration von Konstruktoren ermöglicht es, die verschiedenen Varianten eines Konstruktortyps durch frei gewählte Namen zu bezeichnen. Konvention: Konstruktoren = Bezeichner mit Großbuchstaben beginnend Typen und Werte = Bezeichner mit Kleinbuchstaben beginnend

6 Programmierung 1 - Repetitorium 6.2 Enumerationstyp datatype day = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday Die Werte des Typs day werden durch nullstellige Konstruktoren beschrieben, die wie Konstanten verwendet werden können. fun weekend Saturday = true | weekend Sunday = true | weekend _ = false Typ: weekend : day bool map weekend [ Monday, Wednesday, Friday, Saturday, Sunday ] = [ false, false, false, true, true ] Typen, die nur mit Hilfe von nullstelligen Konstruktoren definiert sind, werden als Enumerationstyp bezeichnet. vordeklarierter Enumerationstyp: datatype order = LESS | EQUAL | GREATER

7 Programmierung 1 - Repetitorium 6.3 Typsynonyme type point = real * real point ist hierbei kein neuer Typ, sondern eine neue Bezeichnung für einen bereits existierenden Typ. sinnvolle Verwendungen : datatype object = Circle of point * real | Triangle of point * point * point Wir können auch einen neuen Typ einführen : datatype point = P of real * real P ( 2.0, 3.0 ) : point fun mirror ( P ( x, y ) ) = P ( ~x, y )

8 Programmierung 1 - Repetitorium 6.4 Ausnahmen Ausnahmen sind Werte des Typs exn. Neue Ausnahmen deklariert man mithilfe von exception. exception New exception Newer of int New sowie Newer sind Ausnahmekonstruktoren, diese können wie normale Konstruktoren verwendet werden. Zusätzlich kann man mit Ausdrücken der Form raise e die Ausnahme e werfen (e vom Typ exn) raise Newer 6 !Uncaught exception: Newer 6 Raise-Ausdrücke liefern keinen Wert, daher können sie jeden Typ annehmen.

9 Programmierung 1 - Repetitorium 6.4 Ausnahmen Geworfene Ausnahmen können mithilfe von Handle-Ausdrücken gefangen werden. ( raise New ) handle New => ( ) ( raise Newer 7 ) handle Newer x => 7 fun test f = f() handle Newer x => x | Overflow => ~1 Beim Programmieren mit Ausnahmen sind manchmal Sequenzialisierungen ( e 1 ;... ; e n ) hilfreich. Auswertung einer Sequenz: Alle Teilausdrücke e 1,..., e n von links nach recht auswerten. Bei Terminierung aller Ausdrücke, liefert die Sequenz den Wert des letzten Teilausdrucks e n. (e 1,...,e n ) = let val _ = e 1... val _ = e n-1 in e n end

10 Programmierung 1 - Repetitorium 6.5 Arithmetische Ausdrücke type var = int (Variablen als ganze Zahlen) datatype exp = C of int | V of var | A of exp*exp | M of exp*exp Jede Ausdrucksform ( Konstante, Variable, Addition, Multiplikation ) wird durch einen entsprechenden Konstruktor realisiert. Darstellung der rekursiven Struktur von exp: exp int var C V M A

11 Programmierung 1 - Repetitorium 6.5 Arithmetische Ausdrücke ( 2 x + y ) * ( x + 3 ) val e = M ( A ( M ( C 2, V 1 ), V 2 ), A ( V 1, C 3 ) ) M A MVMV VCVC CVCV Um den Ausdruck auszuwerten, benötigen wir eine Umgebung, die den Variablen x und y Werte zuweist. { x 5, y 3 } val env = fn 1 => 5 | 2 => 3 | _ => raise Unbound datatype exp = C of int | V of var | A of exp*exp | M of exp*exp

12 Programmierung 1 - Repetitorium 6.5 Arithmetische Ausdrücke Unser Ziel : die Evaluierungsprozedur eval : exp env int fun eval ( C c ) _ = c | eval ( V v ) env = env v | eval ( A (e,e) ) env = eval e env + eval e env | eval ( M (e,e) env = eval e env * eval e env

13 Programmierung 1 - Repetitorium 6.6 Optionen datatype a option = NONE | SOME of a NONE ist die uneingelöste Option, SOME ist die eingelöste Option. fun get xs n = SOME (List.nth(xs,n)) handle Subscript => NONE liefert das n-te Element einer Liste als eingelöste Option, wenn es existiert. get [3,4,5] 2 = SOME 5 get [3,4,5] 3 = NONE fun valOf (SOME x) = x | valOf NONE = raise Option.Option erlaubt bequemen Zugriff auf eingelöste Optionen fun isSome NONE = false | isSome (SOME _) = true testet, ob es sich um eine eingelöste Option handelt

14 Programmierung 1 - Repetitorium 6.7 Case-Ausdrücke und abgeleitete Formen fun sign x = case Int.compare (x,0) of LESS => ~1 | EQUAL => 0 | GREATER => 1 case e of M1 => e1 |... | Mn => en = ( fn M1 => e1 |... | Mn => en ) e if e1 then e2 else e3 = (fn true => e2 | false => e3) e1

15 Programmierung 1 - Repetitorium 6.8 Bäume informell und formal Größe des Baumes = Anzahl der Knoten des Baumes Pfad = Verbindung zwischen 2 bel. Knoten eines Baumes Länge des Pfades = Anzahl der Kanten des Pfades Tiefe des Knotens = Länge des Pfades von der Wurzel zu den Knoten Tiefe des Baumes = Max. Tiefe seiner Knoten Wurzel Kante Knoten Marke 1.Nachfolger 2.Nachfolger 3.Nachfolger Vorgänger Blatt

16 Programmierung 1 - Repetitorium 6.8 Bäume informell und formal Eigenschaften von Bäumen : 1.Zwischen 2 Knoten eines Baumes existiert immer genau ein Pfad. 2.Die Wurzel eines Baumes hat keinen Vorgänger und alle anderen Knoten haben genau einen Vorgänger. Tiefe eines Knotens = Länge seiner Adresse u Adresse des Knotens Adresse seines n-ten Nachfolgers [ ] [1][2][3] [1,1][3,1][3,2][3,3] [1,1,1][1,1,2][1,1,3]

17 Programmierung 1 - Repetitorium 6.8 Bäume informell und formal Bäume mit genau einem Knoten heißen atomar. Bäume mit mind. zwei Knoten heißen zusammenhängend. Die Blätter eines Baumes sind alle Knoten ohne Nachfolger. Jeder Baum hat genau eine Wurzel, mindestens ein Blatt und mind. einen Knoten. Ein Baum ist aus seinem Kopf (Marke der Wurzel) und seinen Unterbäumen (Teilbäume der Nachfolger der Wurzel) zusammengesetzt. ( x, [ t1,..., tn ] ) ( 1, [ ( 2, [ ] ), ( 7, [ ] ), ( 7, [ ] ) ] ) Ein Baum heißt linear gdw. jeder Knoten höchstens einen Nachfolger hat. Ein Baum heißt binär gdw. jeder Knoten außer den Blättern genau zwei Nachfolger hat. Ein Baum heißt balanciert gdw. alle Blätter gleiche Tiefe haben. Jeder atomare Baum ist linear, binär und balanciert.

18 Programmierung 1 - Repetitorium 6.9 Ein ausführbares Modell für Bäume datatype a tree = T of a * ( a tree list ) T ( 1, [ T ( 2, [ ] ), T ( 7, [ ] ), T ( 7, [ ] ) ] ) fun head (T(x,_)) = x fun dst (T(_,ts)) n = List.nth(ts,n-1) liefert den Kopf des Baumes liefert den n-ten Unterbaum von t fun atomic (T(_,ts)) = null ts testet, ob ein Baum atomar ist

19 Programmierung 1 - Repetitorium 6.9 Ein ausführbares Modell für Bäume fun subtree t nil = t | subtree t (n::ns) = subtree (dst t n) ns fun node t ns = (subtree t ns; true) handle Subscript => false fun leaf t ns = atomic (subtree t ns) handle Subscript => false testet für einen Baum, ob es sich bei einer Liste um einen Knoten des Baumes handelt testet für einen Baum, ob es sich bei einer Liste um ein Blatt des Baumes handelt fun label t ns = head (subtree t ns) liefert die Marke eines Knotens liefert zu einem Baum und einer Liste den zugeordneten Teilbaum fun pred t nil = raise Subscript | pred t ns = (subtree t ns; rev(tl(rev ns))) liefert zu einem Baum und einem Knoten den Vorgänger des Knotens

20 Programmierung 1 - Repetitorium 6.9 Ein ausführbares Modell für Bäume fun succ t ns n = let val ns = in subtree t ns; ns end fun size (T(_,ts)) = foldl op+ 1 (map size ts) fun depth (T(_,ts)) = 1 + foldl Int.max -1 (map depth ts) liefert die Größe eines Baumes ( = 1 + Summe der Größen seiner Unterbäume ) liefert die Tiefe eines Baumes ( = 1 + max. Tiefe seiner Unterbäume ) liefert zu einem Baum, einem Knoten und einer Zahl n den n-ten Nachfolger des Knotens

21 Programmierung 1 - Repetitorium 6.10 Test auf Balanciertheit Ein Baum ist genau dann balanciert, wenn für jeden seiner Teilbäume t gilt, dass alle seine Unterbäume die gleiche Höhe haben bzw. alle Blätter die gleiche Tiefe haben. fun balanced t = let exception Unbalanced fun depthb (T(_,nil)) = 0 | depthb (T(_,t::tr)) = 1 + foldl forward (depth t) tr and forward (t,n) = if depthb t = n then n else raise Unbalanced in (depthb t; true) handle Unbalanced => false end depthb und forward sind verschränkt rekursiv, daher ist eine Deklaration mit and erforderlich.

22 Programmierung 1 - Repetitorium 6.11 Linearisation und Projektionen Eine Liste heißt Linearisierung eines Baumes, wenn sie genau die Knoten des Baumes enthält (ohne Doppelauftreten), und wenn sie die Knoten jedes Teilbaumes als Segment enthält. Die Projektion einer Liste von Knoten erhält man, indem man jeden Knoten durch seine Marke ersetzt. Präfixlinearisierung : 1.Für jeden Teilbaum gilt : Die Wurzel erscheint vor den Knoten der Unterbäume. 2.Für jeden Teilbaum mit mindestens zwei Unterbäumen gilt : Die Knoten der Unterbäume erscheinen in der Reihenfolge der Unterbäume. fun project t nss = map (label t) nss fun pre (T(x,ts)) = x :: List.concat (map pre ts)

23 Programmierung 1 - Repetitorium 6.11 Linearisation und Projektionen Postfixlinearisierung : fun post (T(x,ts)) = List.concat (map post [x] Analog zur Präfixlinearisierung, nur mit dem Unterschied, dass die Wurzel eines Teilbaums diesmal nach dem Knoten seiner Unterbäume erscheint Präfix : [ 3, 0, 5, 4, 1, 2, 7, 7 ] Postfix : [ 5, 0, 4, 2, 7, 7, 1, 3 ]


Herunterladen ppt "Programmierung 1 - Repetitorium WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner Homepage:"

Ähnliche Präsentationen


Google-Anzeigen