Zuweisungsorientierte Programmierung. Wesentliches Element Funktionaler Programmierung ist den Wert einer Funktion zu berechnen und an das aufrufende Programm zurückzugeben. Übergibt man einer Funktion Parameter, so bleiben diese unverändert. Bei der Berechnung werden neue Objekte erzeugt. Beispiel: Einfügen in Listen (funktional) l = [1;2;4] Anwendung der Funktion insertSort(3,l) ergibt: lneu = [1;2;3;4] Dabei werden l und lneu durch die Inhalte verschiedener Speicherbereiche repräsentiert. Anderes Beispiel: der schrittweise Aufbau einer 4- elementigen Liste produziert auch die Listen [] [a], [a;b], [a;b;c]. Unmittelbar speichereffizienter ist es hier, das jeweils nächste Element unmittelbar an die vorhandene Repräsentation der Liste im Speicher anzuhängen). Ein solches direktes Operieren auf „Elementen“(„hier konnt ich leider nicht die Schrift entziffern„) ist das Kernkonzept der etsich damit zuweisungsorientierten Programmierung. Sprachkonzept unterscheidet sich damit fundamental vom Funktionalen und baut direkt auf Architektur der von- Neumann- Maschine mit linearen Speicher auf. Die Inhalte des Speichers kennzeichnen also den Zustand der Berechnung. Das Programm bzw. seine Einzelschritte ändern diesen Zustand: jeweils letzter Berechnungszustand ist Eingangszustand für die nächste Berechnung. Im Unterschied zur funktionalen Programmierung wird auf den Objekten selbst operiert. u 1 v 2 w 3 incr u u 2 v 2 w 3 Bei funktionaler Programmierung würde eine weitere Speicherzelle mit dem Wert 2 belegt werden. Realisierung des Konzepts „Zuweisung“. Mit einer Zuweisung wird einer Variablen v das Resultat eines Ausdrucks E zugewiesen. Syntax: <var_name> <zuweisungsop><E> Beispiel: Pascal v:= 17/3; v:= v + 1; C v:=17/3; v = v+1; In Ocaml ist C- artige Zuweisung nicht möglich, denn der syntaktisch Korrekte Ausdruck let rec v = v+1;; entspricht einer nicht terminierenden rekursiven Funktion. Möchte man in OCAML mit Variablen in o.g. Sinne arbeiten, so muss ausgedrückt werden, dass der „Funktionsname“ die Adresse einer Speicherzelle (bzw. der Verweis auf einem Speicherbereich ist). Dies geschieht mittels Referenzen (Zeiger, Pointer). Referenz ist ein Verweis auf einer Adresse eines Speicherbereichs der von- Neumann- Maschinen. Deklaration einer Variablen in OCAML: let v = ref 1;; Gleichzeitig Vereinbarung von v als Zeiger und Belegung der Zelle, auf die v verweist, mit dem Wert 1. Syntax: let <name> = ref <expression> ;; Der Typ wird aus <expression> ermittelt. Zuweisung in OCAML: Die Pascal Zuweisung v := v+1; lautet in OCAML v:= !v + 1; Weiterer Begriff: Prozeduren (vs. Funktionen). Im imperativen Sprachen arbeitet man häufig mit Prozeduren, also Sequenzen von Anweisungen, die eine Variablen Belegung modifizieren, jedoch im Gegensatz zu Funktionen keinen Wert zurückliefern. Beispiel: (In Pascal) function ggT (a,b: Integer) : Integer; procedure druck_ggT(a,b: Integer); Man kann Prozeduren als Funktionen auffassen die den Zustand der Berechnung (der Maschine) ändern, aber keinen Rückgabewert produzieren. OCAML: Da hier eine Funktion stets einen Wert zurückgeben muss, wird definiert, dass eine Prozedur das Element „()“ ^= ‚unit’ zurückgibt. (So wie void in Java). Strukturierte Datentypen: Records und Produktsorten. Häufig möchte man Datentypen konstruieren, die Teildaten zu einer inhaltlichen zusammenhängenden Einheit zusammenfassen. Dazu verwendet man Records. Vereinbarung solcher Records. a) in Pascal: type <record_name> „ = record“ { <element_name>“,“<type>“;“}* „end;“ b) in Ocaml: type <record_name> „ = {„ <dokument_name> „ ; “ <type>“;“ … „};;“ Pascal: ZÜ JAVA: TÜ. Beispiel in Ocaml: type c complex = { real: float; imag: float} Erzeugung: let c = {real = 2.0; imag = 30 } Zugriff über Punktnotation: c.real ergibt 2.0 Zusatzbemerkung: Records sind in OCAML zunächst nicht variabel, soll dies der Fall sein, so müssen Teilelemente als „mutable“ Attribute werden. type punkt = { mutable x: float; mutable y: float};; Zuweisung tatsächlicher Werte: let p1 {mutable x = 1.0,… Zuweisung: p1.x 3.0 Weitere Bemerkung: Eine Referenz in OCAML wird aufgefasst als ein Record mit einem einzigem Element, welches mutable ist, also: type ’a ref = { mutable content ’a};; Dynamische Datenstrukturen : Mit Hilfe von Records lassen sich die aus der funktionalen Programmierung bekanten rekursiven Sorten (Listen, Bäume,…) zuweisungsorientiert in imperativen Programmiersprachen nachempfinden. Kernstücke sind Records, die rekursive Struktur haben. Beispiel: für Liste von Ganzzahlen 1 4 Referenzen 6 nil Inhalt Record besteht aus zwei Teilen: Erste Konnpunkte enthält das eigentliche Element (‚Nutzinfo’); zweite Komponente enthält Referenz auf weiteren Record desselben Typen, der hier das nächste Listenelement darstellt. Für die Liste ergeben sich also folgende Typdefinitionen; type Lref = Nil | Ref of lnode and Lnode = { mutable valu : int; mutable next: Lref};; Im folgenden Formatierung der Standardoperation für die uns von dem funktionalen Sequenzen her beannten Operationen first, last append.