• Bisher besprochene Konstrukte von SML: Deklarationen Deklarationen: Binden von Werten an Namen Wirkung: Erweiterung von Typ- und Wertumgebung Bsp. ( Moscow - ML - Interpreter) - val pi =3.14; Γ‘ = Γ ⊕ {pi ! (val, int)} > val pi = 3.14 : real !‘ = ! ⊕ {pi ! (val,3.14)} - val a:int =4; val b:int = let val a:char =#"A" in ord(a)+32 end - a; > val a = 4 : int > val b = 93 : int • Bisher besprochene Konstrukte von SML: Ausdrücke Ausdrücke ... sind aus Kontantenbezeichnern, Variablenbezeichern und Funktionsanwendungen aufgebaut; haben einen eindeutig inferierbaren Typ, werden zu einem Wert diesesTyps ausgewertet: Bsp. ( Moscow - ML - Interpreter) -pi * 10.0 *10.0 > val it = 314.0 : real Γ‘ = Γ ⊕ {a! ! (val, int), b ! (val, int)} !‘ = ! ⊕ {a ! (val, 4), b !(val, 93)} -val A = pi * 10.0 *10.0 > val A = 314.0 : real Eingebaute Funktionen Analyse von Ausdrücken Die eingebaute Funktion ord pi : Variablenbezeichner, an den Wert 3.14 gebunden 10.0 : Konstantenbezeichner, zum Typ real gehörend * : Infixoperator der Multiplikationsfunktion -ord(#"A") - 12; > val it = 53 #“A“ : Konstantenbezeichner, zum Typ char gehörend 12 : Konstantenbezeichner, Typ int - : Infixoperator der Subtraktionsfunktion ord : eingebaute Funktion mit dem Namen ord Typ Wenn der Wert des Ausdrucks an den Namen A statt an den Standardergebnisnamen it gebunden werden soll: Analyse einfacher Ausdrücke pi * 10.0 *10.0 Wert Flächeninhalt A eines Kreises mit r =10.0 LE ord ist ein Bezeichner und damit auch ein einfacher SML – Ausdruck. Wir fragen den Compiler, woran ord gebunden ist: - ord; > val it = fn : char -> int ord ist eine Funktion aus der Funktionenmenge " # $ und ordnet jedem auf der Tastatur erzeugbaren Zeichen eine in der ASCII – Tabelle festgelegte int - Zahl zu. Der SML Interpreter meldet, daß ord an einen Wert vom Typ „Funktion“ (fn) gebunden ist und gibt als Typ für diesen Wert char -> int an. Funktionen sind in SML also Werte vom Funktionstyp (Pfeiltyp) !! Funktionsanwendung (… applikation) Infixschreibweise von Funktionsanwendungen Applikation von ord Infixschreibweise von Funktionen ord ist der Name einer Funktion. Funktionen „ruft man in der Mathematik mit dem Funktionsargument auf“ und meint damit die Bestimmung des Funktionswertes, der durch die Funktion dem Argument zugeordnet wird: Bsp.: f(5) = 12 bedeutet : (5,12) ist ein Paar aus f. In der Informatik „wendet man eine Funktion auf ein Argument an“: Bsp.: ord(#“A“) ist eine Funktionsapplikation Funktionsapplikationen sind (einfache) Ausdrücke und werden zu einem Wert ausgewertet: - ord(#"A"); > val it = 65 : int Infixschreibweise - Präfixnotation Bsp.: add: X # ; (a,b) # a + b (+ ist hier der Additionsoperator der Mathematik) add(2,3) ist also die Summe von 2 und 3, Infixschreibweise: 2 + 3 Applikationen von arithmetischen und booleschen Funktionen werden in SML i. a. in Infixnotation aufgeschrieben. Der Ausdruck 2+3 ist in SML die voreingestellte Schreibweise für die Anwendung der Additionsfunktion add auf das Argument (2,3) Definition von Funktionen in SML Infixschreibweise vs. Präfixschreibweise Um von der Infixschreibweise der Addition zur Präfixschreibweise mit dem Funktionsnamen add zu kommen, genügen wenige SML – Zeilen: - op+; > val it = fn :int * int -> int - val add = op+; > val add = fn :int * int -> int - add(2,3); > val it = 5 : int -add(2,3)+5; > val it = 10 : int - add(2,6)*10 - ord(#"A")+5; > val it = 20 : int Addition, Multiplikation, .. sind Funktionen, die einem Paar von Zahlen eines Zahlentyps (int, real) eine Zahl diesen Typs (ihre Summe) als Funktionswert zuordnen. op+ : Name einer Funktion, die in Infixschreibweise mit dem Operator + notiert wird Selbstdefinierte Funktionen Wir haben oben den Term pi * 10.0 *10.0 auswerten lassen. Der Wert des Termes stellt den Flächeninhalt eines Kreises mit r = 10.0 LE dar. Die mathematische Funktion AKreis: ℜ+ → ℜ+; r ! pi*r2 ist die Funktion, die jedem Radius r die Maßzahl des Flächeninhaltes eines Kreises gleichen Radius zuordnet: AKreis(10) = 314.0 AKreis(2.7) = 22.8906 In SML realisiert man diese Funktion durch einen Funktionsausdruck: AKreis: ℜ+ → ℜ+; r ! pi*r2 SML: fn (r : real) => (3.14 *r * r):real Funktionsanwendung (bei noch anonymen Funktionsausdrücken) Funktionsanwendung Die Zeichenreihe fn (r : real) => (3.14 *r * r):real ist ein SML – Ausdruck vom Typ real # real. Will man den Flächeninhalt eines Kreise berechnen, schreibt man in SML hinter diesen Funktionsausdruck einen Ausdruck, dessen Wert (vom Typ real) den Radius darstell: (fn (r : real) => (3.14 *r * r):real) (10) Ausdruck vom Funktionstyp Ausdruck vom Argumenttyp real → real - (fn(r:real)=>(3.14*r*r)) real (10.0); > val it = 314.0 : real Beispiele I Bindung von Funktionen an Namen Die Verwendung von Funktionsausdrücken ohne Bindung an einen Namen macht wenig Sinn, da man den Funktionsausdruck bei jeder Applikation neu aufschreiben muß. Da Funktionen aber Werte sind, kann man den definierenden Ausdruck mit einer val – Deklaration an einen Namen binden: - val AKreis = fn(r:real)=>(3.14*r*r); > val AKreis = fn : real -> real - AKreis(10.0); > val it = 314.0 : real Die Funktionsapplikation läßt sich nach dieser Deklaration wesentlich einfacher durchführen, da „AKreis“ nun den Funktionsausdruck repräsentiert. Nach dieser Deklaration steht die Funktion AKreis auch für den Aufbau neuer Ausdrücke zur Verfügung. Beispiele II Den Flächeninhalt eines Kreisringes mit äußerem Radius ra und innerem Radius ri berechnet man wie folgt : Um Strings zu konkatenieren gibt es in SML den eingebauten Infix – Konkatenationsoperator ^ . AKR(ra,ri) = 3.14 *ra*ra – 3.14*ri*ri Real – Zahlen können mit der Funktion Real.toString(...) in eineZeichenfolge (String) konvertiert werden. AKR ist eine Funktion mit zwei Argumenten (einem Paar von Radien, beide vom Typ real). Zugehörige SML – Funktion, welche die vorher definierte Funktion AKreis verwendet : val AKR = fn (ra:real,ri:real):real*real=> AKreis(ra)- AKreis(ri); > val AKR = fn : real * real -> real - AKR(10.0,1.0); Die Funktion KR_text ist eine Funktion, die zu einem Paar von Radien vom Typ real als Funktionswert einen String mit zusätzlichem Text als Antwortstring berechnet: -load “Real“ {* macht toString verfügbar *} - val KR_text = fn (ra:real,ri:real)=> " ra = "^Real.toString(ra)^", ri = " ^Real.toString(ri)^" A ="^Real.toString(AKR(ra,ri)); > val KR_text = fn : real * real -> string - KR_text(10.0,1.0); > val it = 310.86 : real > val it =" ra = 10.0, ri = 1.0 A = 310.86" : string