Informatik 3 WS 2002/3 http://www.cs.inf.ethz.ch/37-003/ Prof. Jürg Gutknecht ETH Zürich 29. März, 2003 1 Themenübersicht Programmierparadigmen (1) • Imperative Programmierung ¾Nichtdeterminismus ¾Guarded Commands ¾Unity 2 Themenübersicht Programmierparadigmen (2) • Funktionale Programmierung ¾ Einführung in die Sprache SML ¾ Funktionen, Höhere Funktionen ¾ Datentypen, Konstruktoren ¾ Typeninferenzmechanismus ¾ Parametrische Polymorphie ¾ Listen- und Baumstrukturen ¾ Fallstudie Interpreter ¾ Module und Funktoren, Abstrakte Datentypen ¾ Evaluations Strategien, Lazy Evaluation 3 Themenübersicht Programmierparadigmen (3) • Logische Programmierung ¾Einführung in Prolog ¾Horn Klauseln ¾Deduktionsmaschine • Deskriptive Programmierung ¾Einführung in XML ¾Tags und Attribute ¾Meta Beschreibung (Schemas) 4 Nichtdeterministische Imperative Programmierung 5 Imperative Programmierung Formale Grundbegriffe • Zustandsraum X • Prädikate P, Q, ... über X • Anweisungen S, T, ... ¾Zustandstransformator x → S(x) ¾Prädikatentransformator Q → wp(S, Q) • Hoare Triplet { P } S { Q } P ⇒ wp(S, Q) weakest precondition 6 Imperative Programmierung Guarded Commands (Dijkstra) • • • • • • • Fehlerhalt Anweisung abort Neutrale Anweisung skip Mehrfachzuweisung x, y, ... := E, F, ... Sequenz S; T Guarded Command P → S Alternative if P → S | Q → T | … fi Repetition do P → S | Q → T | … od nichtdeterministische Auswahl 7 Guarded Commands Semantik • Semantik der Zuweisung ¾Zuweisung x := E ¾wp(x := E, Q) = Qx := E in Q x durch E substituieren • Zwei Implementationen von x, y := y, x ¾t := x; x := y; y := t (x – (x – y ) = X) ∧ (x - y = Y) ¾ x := x + y; (y = X) ∧ (x + y - y = Y) y := x – y; (x - y = X) ∧ (y = Y) x := x – y (x = X) ∧ (y = Y) Q 8 Guarded Commands Sortieralgorithmus • Nichtdeterministische Formulierung H :⇔ (a, b, c) ist Permutation von (A, B, C) a, b, c := A, B, C; { H } Invariante do a > b → a, b := b, a { H } | b > c → b, c := c, b { H } od Termination ? { (a ≤ b ≤ c) ∧ H } • Sequentielle Implementation ¾Bubblesort Ueberspezifikation 9 Guarded Commands Problem des Stipendienbetrügers • f, g, h lexikografisch geordnete Namen von Studierenden, Stipendiaten, Angestellten Crook(x) :⇔ (∃ i, j, k: x = f(i), g(j), h(k)) H :⇔ (∀x: x < min(f(I), g(J), h(K)): ¬Crook(x)) I, J, K := 0, 0, 0; { H } Sentinel do garantiert f(I) < g(J) → I := I + 1 { H } Termination | g(J) < h(K) → J := J + 1 { H } | h(K) < f(I) → K := K + 1 { H } od { (f(I) ≥ g(I) ≥ h(K) ≥ f(I)) ∧ H } 10 Unity Formalismus Problem: Nächstmögliche Meetingzeit • Terminkalender f Chandy & Misra ¾(∀t: f(t) ≥ t, f(f(t)) = f(t)) • f, g, h Terminkalender Unity Programm t := 0; t := f(t) || t := g(t) || t := h(t) ¾ Termination: Sobald Fixpunkt erreicht ist ¾ Faire Auswahl: Jede Zuweisung kommt nach endlich vielen Schritten an die Reihe 11 Unity Formalismus Problem: Nächstmögliche Meetingzeit • Invariante (∀s: s < t: s ist keine mögliche Meetingzeit) • Beweis mit vollständiger Induktion ¾Wahr bei Programmstart ¾Wahr nach jeder Ausführung einer Zuweisung 12 Unity Formalismus Problem: Nächstmögliche Meetingzeit • Implementationen ¾Von Neumann Rechner oder Ring • LOOP r := f(r); r := g(r); r := h(r) END; • LOOP r := f(r); r := g(r); r := f(r); r := h(r) END Zentraler ¾Verteiltes System Koordinator • r := max (f(r), g(r), h(r)) f f Token Ring g h g h 13 Programmspezifikation Ebenenmodell Problem •Guarded Commands Spezifikation •Unity •... Implementation Systemarchitektur Von Neumann SMP Verteiltes System14 Funktionale Programmierung 15 Programmierparadigmen Kommentar von John Backus • The assignment statement splits programming in two worlds. The first world is the world of the right-hand sides. This is an orderly world of expressions with useful algebraic properties. It is the world in which useful computation takes place. • The second world is the world of statements. The primary statement is the assignment statement itself. All the other statements exist in order to make it possible to perform a computation that is based on this primitive construct: the assignment statement itself. • The world of statments is a disorderly one, with few useful mathematical properties. Structured programming can be seen as a modest effort to introduce some order to this chaotic world, but it accomplishes little in attacking the fundamental problems created by word-at-a-time von Neumann-style of programming. 16 Funktionale Programmierung Grundprinzipien • Speicherloses Ablaufsmodell ¾ Wegabstrahierung von Speicherzuständen und Zustandsübergängen • Funktion als Programmelement ¾ Resultat als Funktion der Argumente y = f(x) ¾ Keine Nebeneffekte • Komposition von Funktionen/ Programmen ¾ (g°f) (x) = g (f (x)) • Höhere Funktionen ¾ Funktionen als Argumente und Resultate g = F(f) 17 Standard ML als Referenzsprache • Core Language für Programming-in-the-Small ¾ Starke Typisierung mit Inferenzmaschine ¾ Pattern Matching Mechanismus für Argumente ¾ Funktionen als „First-Class-Citizens″ ¾ Konkrete und abstrakte Datentypen ¾ Polymorphie ¾ Interaktive Abarbeitung • Modulsystem für Programming-in-the-Large ¾ Structures ¾ Signatures ¾ Functors 18 Funktionen λ-Ausdrücke • fn Expression fn x => E else any fn x0 => E0 | x1 => E1 | ... | _ => En fn (x0, y) => E0 | (x1, y) => E1 ... | _ => En • Beispiele fn x => x + 1 (fn x => x + 1) 2002 (fn x => x + 1)((fn x => x + 1) 7) (fn x => x + 1)(fn x => x + 1) 7 linksassoziativ! fn 0 => ″red″ | 1 => ″green″ | 2 => ″blue“ 19 Werte und Bereiche Definitionsschemata • val und let ... in ... end val euler = 0.5772 val succ = fn x => x + 1 val color = fn 0 => ″white″ | _ => ″black″ val f = fn x => let val d = 2.72 val g = fn t => t * t * t in g (x – e) end • local ... in ... end local val pi = 3.14 val sq = fn x => x * x in val ringarea = fn (R, r) => pi * (sq R – sq r) end 20 Beispiel Wochentagsbestimmung Wochentag Zeller‘sche Formel • (2.61m – 0.2 + d + y + y ÷ 4 + c ÷ 4 – 2c) mod 7 c = Jahrhundert, y = Jahr im Jahrhundert, m = Monat – 2 im Jahr, d = Tag im Monat$ • local Qualifiziert mit val floor = Real.floor Modulnamen val real = Real.fromInt val zc = fn (d, m, y, c) => (floor (2.61 * real m – 0.2) + d + y + y div 4 + c div 4 – 2 * c) mod 7 in val zeller = fn (d, 1, y) => zc (d, 11, (y-1) mod 100, (y–1) div 100 + 1) | (d, 2, y) => zc (d, 12, (y-1) mod 100, (y–1) div 100 + 1) | (d, m, y) => zc (d, m-2, y mod 100, y div 100 + 1) end Pattern 21 Beispiel Integer-to-String Hinweis Rekursive Formulierung val rec radix = fn (n, digits) => let Teilstring val b = size digits val digit = fn n => str (String.sub (digits, n)) val radix′ = fn (true, n) => digit n concatenate | (false, n) => radix (n div b, digits) ^ digit (n mod b) in radix′ (n < b, n) end radix (13, ″01″) liefert ″1101″ 22 Standard ML Library Typbezogene Module (Structures) • Bool Structure Bool.not, Bool.fromString, Bool.toString NONE T.fromString • Char Structure SOME t Char.chr, Char.ord, Char.toUpper, Char.toLower Char.contains, Char.notContains option Datentyp • Int Structure Int.abs, Int.min, Int.max, Int.fromString, Int.toString • Real Structure Real.trunc, Real.round, Real.floor, Real.ceil, Real.fromInt • String Structure String.sub, String.substring, String.concat 23 Funktionen höherer Ordnung Funktionen als Argumente • • • • • • sum (n) = n + n-1 + ... + 1 sq (n) = (2*n – 1) + (2*(n-1) – 1) + ... + (2*1 – 1) fadd (f, n) = f(n) + f(n-1) + ... + f(1) fac (n) = n * n-1 * ... * 1 fmul (f, n) = f(n) * f(n-1) * ... * f(1) fgen (g, f, n) = g(f(n), g(f(n-1), ..., f(1)) ... )) 24 Funktionen höherer Ordnung fadd/fmul in SML • val rec fadd = fn (f, n) => let val condfadd = fn true => 0 │false => f (n) + fadd (f, n-1) in condfadd (n < 1) end 25 Funktionen höherer Ordnung fgen in SML • val rec fgen = fn (g, f, e, n) => let Neutral val condfgen = fn Element true => e │false => g (f (n), fgen(g, f, e, n-1)) in condfgen (n < 1) end 26 Funktionen höherer Ordnung sum, sq, fac als fgen • op - Notation val op ♣ = fn (x, y) => x ♣ y • Spezialisierungen von fgen val sum = fn n => fgen (op +, fn x => x, 0, n) val sq = fn n => fgen (op +, fn x => 2* x – 1, 0, n) val fac = fn n => fgen (op *, fn x => x, 1, n) 27 Funktionen höherer Ordnung Funktionen als Resultat • Funktion als Funktionswert val F = fn (...) => fn (...) => ... • Komposition val comp = fn (f, g) => fn x => g(f(x)) • Iteration val rec iter = fn 0 => (fn f => fn x => x) │ n => (fn f => fn x => f(iter (n-1) f x)) 28 Funktionen höherer Ordnung Curry‘sche Isomorphie (Haskell B. Curry) • Funktionenräume Abbildungen ¾A, B Mengen ¾BA Menge aller Funktionen von A nach B • Curried Functions ¾X, Y, Z Mengen X X x Y Y ≅ (Z ) ¾Z Curried X f ∈ Z X x Y ↔ f′ ∈ (Z Y) via f′ (x) (y) = f (x, y) ¾val curry = fn f => fn x => fn y => f (x, y) ¾val uncurry = fn f′ => fn (x, y) => f′ (x) (y) 29 Funktionen höherer Ordnung Beispiel Hashing • Hashfunktion mit Kollisionsbehandlung Hash (k, i) := (k + h (k, i)) mod N • Kollisionsbehandlung als Parameter ¾val H = fn h => fn (k, i) => (k + h (k, i)) mod N ¾val HashL = H (fn (k, i) => i) Konstante val HashQ = H (fn (k, i) => i * i) val HashD = H (fn (k, i) => i * ((N–2) - k mod (N–2)) 30 Funktionen höherer Ordnung Beispiel Hashing • Sondierung val rec H = fn key => let HH = fn (h, i, key) => let check = fn true => h (i, key) │false => HH (h, i + 1, key) in check (NoCollision (h (i, key)) end in HH (HashD, 0, key) end 31 Abgeleitete SML Formen fun, case, if • fun succ x = x + 1 • fun sum 1 = 1 │ sum n = sum (n – 1) + n • fun fgen (g, f, e, n) = case n < 1 of true => e │ false => g (f (n), fgen(g, f, e, n-1)) • fun fgen (g, f, e, n) = if n < 1 then e else g (f (n), fgen(g, f, e, n-1)) 32 Records und Tupel • Records { name: string, age: int } val president = { name = „bush“, age = 57 } #name(president) • Tupel int * bool * real { 1: int, 2: bool, 3: real } val n: int * bool * real = (7, true, 0.9) val n = { 1 = 7, 2 = true, 3 = 0.9 } 33 Datentypen und Polymorphie "Konstruktor" • Datentypen datatype color = red │ green │ blue • Parametrische Polymorphie ¾type α set = α → bool ¾type α → α ¾let val Id = fn x => x in (Id 3, Id true) end ¾datatype α tree = empty )) L I ,N │ node of α * α tree * α tree L I ,N "Konstruktor" nod 5, 2 ( e N (1 e d o n , L I 7 34 Listen Head, Tail • datatype α list = nil │ :: of α * α list • 2 :: 1 :: nil Abgeleitete cons [21] Form Exception • fun head [] = raise Empty│ head (h :: t) = h • fun tail [] = raise Empty │ tail (h :: t) = t SOME t NONE • fun last [] = raise Empty │ last [x] = x │ last (h :: t) = last t 35 Listen Appending • fun length [ ] = 0 │ length (h :: t) = 1 + length t • infixr 5 @ Signatur fun [] @ list = list │ (h :: t) @ list = h :: t @ list • fun rev [] = [] │ rev (h :: t) = (rev t) @ [h] • fun revApd ([], list) = list │ revApd (h :: t, list) = revApd (t, h :: list) 36 Listen Retrieval • fun member (x, []) = false │member (x, h :: t) = x = h orelse member (x, t) • exception Retrieve fun retrieve (kev, []) = raise Retrieve │ retrieve (key, (k, v) :: t) = if key = k then v else retrieve (key, t) • fun nth ([], _) = raise Subscript │ nth (h :: t, 0) = h │ nth (_ :: t, n) = nth (t, n – 1) any handle Overflow => raise Subscript 37 Listen Sections • fun take (_, 0) = [] │ take ([], _) = raise Subscript │ take (h :: t, n) = h :: take (t, n-1) handle Overflow => raise Subscript • fun takewhile (p, []) = [] │ takewhile (p, h :: t) = if p h then h :: takewhile (p, t) else [] 38 Listen Sorting • fun insert (x, []) = [x] │insert (x, h :: t) = if x <= h then x :: h :: t else h :: insert (x, t) • fun sort [] = [] │ sort (h :: t) = insert (h, sort t) 39 Listen Mapping • fun map f [] = [] │ map f (h :: t) = f h :: map f t • fun map f = let fun map_f [] = [] │ map_f (h :: t) = f h :: map_f t in map_f Effizienzsteigerung end durch Binden von f 40 Listen Folding als generische Operation • fun mapPartial f [] = [] │mapPartial f (h :: t) = case f h of NONE => mapPartial f t │ SOME v => v :: mapPartial f t • type ((α * β) → β) → (β → ((α list) → β)) fun foldR f e [] = e │ foldR f e (h :: t) = f (h, foldR f e t) • type ((α * β) → β) → (β → ((α list) → β)) fun foldL f e [] = e │ foldL f e (h :: t) = foldL f (f(h, e)) t • f assoziativ & kommutativ ⇒ foldL f = foldR f41 Listen • • • • Folding Spezialisierungen fun sort s = foldR insert [] s type (α list) list → α list fun concat s = foldR (op @) [] s fun length s = foldR (fn (x, y) => 1 + y) 0 s fun listrev s = foldL (op ::) [] s listrev [ 1, 2, 3 ] foldL (op ::) [] (1 :: [2, 3]) foldL (op ::) (1 :: []) [2, 3] foldL (op ::) (2 :: [1]) [3] foldL (op ::) (3 :: [2, 1]) [] [ 3, 2, 1 ] 42 Listen Paarlisten und Zipping • fun zip f [] [] = [] │ zip f (h::t) (k::u) = f h k :: zip f t u │ zip f x y = error • val addlists = zip plus val mullists = zip times val pairlists = zip pair • pairlists [1, 2, 3, 4] [5, 6, 7, 8] = [(1, 5), (2, 6), (3, 7), (4, 8)] 43 Fallstudie 1: Tautologieerkennung Strategie (Lösung nach C. Ignat) • Definiere allgemeine logische Ausdrücke E unter Verwendung der Operatoren ¬, ∧, ∨, ⇒ • Definiere Regeln zur Transformation eines allgemeinen Ausdrucks E in konjunktive Normalform cnf(E), d. h. in eine Form A ∧ B ∧ C ∧ ..., wobei A, B, C Disjunktionen von Termen der Form Atom oder ¬Atom sind • E Tautologie ⇔ alle Faktoren in cnf(E) sind Tautologien • Faktor A in cnf(E) ist Tautologie ⇔ ein Term in A ist Tautologie oder es existiert ein Paar a, ¬a in A 44 Fallstudie 1: Tautologieerkennung Datentyp Ausdruck mit Konstruktoren • datatype expr = Atom of string | Neg of expr | Disj of expr * expr | Conj of expr * expr • fun implic (p, q) = Disj (Neg p, q) 45 Fallstudie 1: Tautologieerkennung Negative Normal Form nnf • fun nnf (Atom a) = Atom a | nnf (Neg (Atom a)) = Neg (Atom a) | nnf (Neg (Neg p)) = nnf p | nnf (Neg (Conj(p, q))) = Negation nur nnf (Disj (Neg p, Neg q)) auf Atome | nnf (Neg (Disj(p, q))) = angewandt nnf (Conj (Neg p, Neg q)) | nnf (Conj (p,q)) = Conj (nnf p, nnf q) | nnf (Disj (p,q)) = Disj (nnf p, nnf q) 46 Fallstudie 1: Tautologieerkennung Konjunktive Normal Form cnf • fun distrib (p, Conj (q, r)) = Conj (distrib (p, q), distrib (p, r)) | distrib (Conj (q, r), p) Conj (distrib (q, p), distrib (r, p)) | distrib (p, q) = Disj (p, q) • fun cnf (Conj (p, q)) = Conj (cnf p, cnf q) | cnf (Disj (p, q)) = distrib (cnf p, cnf q) | cnf p = p 47 Fallstudie 1: Tautologieerkennung Kriterium und Implementation • fun isTaut (p) = taut (cnf (nnf (p))) • fun taut (Conj (p, q)) = taut p andalso taut q | taut (p) = inter (pos p, neg p) <> [] • fun inter ([], ys) = [] | inter (x::xs, ys) = if List.exists (fn t => (t = x)) ys then x::inter (xs, ys) else inter (xs, ys) 48 Fallstudie 1: Tautologieerkennung Gruppierung in pos und neg Atome • exception Cnf • fun pos (Atom a) =[a] | pos (Neg (Atom _)) = [] | pos (Disj (p, q)) = pos p @ pos q | pos _ = raise Cnf • fun neg (Atom _) = [] | neg (Neg (Atom a)) = [a] | neg (Disj (p, q)) = neg p @ neg q | neg _ = raise Cnf 49 Fallstudie 2: Huffmancode Huffmann Trees (Lösung nach C. Ignat) Liste von Trees nach Häufigkeit geordnet • datatype HTree = Leaf of char | Node of HTree * HTree • fun insertT a [] =[a] | insertT (p1:real, h1) ((p2, h2) :: xs) = if p1 < p2 then (p1, h1) :: (p2, h2) :: xs else (p2, h2) :: insertT (p1, h1) xs bottom up • fun consH [(p, h)] = h Konstruktion | consH (a :: b :: xs) = let fun consT (p1, h1)(p2, h2) = des HTrees (p1 + p2, Node (h1, h2)) in consH (insertT (consT a b) xs) end 50 Fallstudie 2: Huffmancode Programm Expandiere die Pfadcodes • fun expandP a = let fun expand (Leaf sym) path = [(sym, path)] | expand (Node(left, right)) path = (expand left (path ^ "0")) @ (expand right (path ^ "1")) in expand a "" end Sortiere Symbole nach • fun huffman x = Häufigkeit let fun sortS [] = [] | sortS ((p:real, sym) :: xs) = insertT (p, (Leaf sym)) (sortS xs) in expandP (consH (sortS x)) end • val l = [ (0.5, #"A"), (0.2, #"B"), (0.1, #"C"), (0.1, #"D"), (0.05, #"E"), (0.05, #"F") ]; run huffman l 51 Fallstudie 3: Command Interpreter Abstract Syntax • datatype command = Assign of (variable x expression) │ Sequence of (command x command) │ Conditional of (expression x command x command) │ Repetition of (expression x command) • datatype expression = Constant of int │ Contents of variable │ Minus of (expression x expression) │ Greater of (expression x expression) │ Times of (expression x expression) 52 • datatype variable = Var of string Fallstudie 3: Command Interpreter Sample Command • WHILE X > Y DO X := X – 1; Z := Z * Z Konstruktoren END • Repetition (Greater (Contents (Var „X“), Contents (Var („Y“)), Sequence (Assign (Var „X“, Minus (Contents (Var „X“), Constant 1)), Assign (Var „Z“, Times (Contents (Var „Z“), Contents (Var „Z“))))) 53 Fallstudie 3: Command Interpreter • • • • • Store datatype value = Value of int datatype store = Store of (name → value) fun get (a, Store f) = f a fun update (Store f, a, v) = Store (assoc [(a, v)] f) fun assoc [] f = f │ assoc ((a0, v0) :: t) f = if a = a0 then v0 else assoc t f 54 Fallstudie 3: Command Interpreter Evaluator • eval: expression → store → value • fun eval (Constant n) s = Value n │ eval (Variable a) s = get (a, s) │ eval (Minus (e1, e2)) s = let val Value v1 = eval e1 s and Value v2 = eval e2 s in Value (v1 – v2) end │ eval (Times (e1, e2)) s = let val Value v1 = eval e1 s and Value v2 = eval e2 s in Value (v1 * v2) end │ eval (Greater (e1, e2)) s = let val Value v1 = eval e1 s and Value v2 = eval e2 s in if v1 > v2 then Value (1) else Value (0) end 55 Fallstudie 3: Command Interpreter Interpreter • fun switch (Value 1) f g s = f s │ switch (Value 0) f g s = g s │ switch (Value n) f g s = error • fun interpret (Assign (v, e)) s = let val a = eval e s in update (s, v, a) end │ interpret (Sequence (c1, c2)) s = interpret c2 (interpret c1 s) │ interpret (Conditional (e, c1, c2)) s = switch (eval e s) (interpret c1) (interpret c2) s │ intepret (Repetition (e, c)) s = switch (eval e s) (interpret (Repetition (e, c)) ° interpret c) Id s 56 Fallstudie 3: Command Interpreter Concrete Syntax • exp ::= aexp [ ”>” aexp ] aexp ::= bexp [”-” aexp ] bexp ::= cexp [”*” bexp ] cexp ::= ”(” exp ”)” │ number │ variable command ::= unitcom [ ”;” command ] unitcom ::= whilecom │ ifcom │ assign whilecom ::= ”WHILE” exp ”DO” command ”END” ifcom ::= ”IF” exp ”THEN” command ”ELSE” command ”END” assign ::= variable ”:=” exp 57 Fallstudie 3: Command Interpreter Parsers • datatype token = Ident of string │ Symbol of string │ Number of int • datatype α possible = Ok of α │ Fail • type α parser = token list → (α x token list) possible 58 Fallstudie 3: Command Interpreter Basic Parsers • fun number (Number n :: s) = Ok (n, s) │ number other = Fail • fun variable (Ident x :: s) = Ok (Var x, s) │ variable other = Fail • literal: string → string parser fun literal a (Symbol x :: s) = if a = x then Ok (x, s) else Fail │ literal a other = Fail 59 Fallstudie 3: Command Interpreter Parser Builders • fun (p1 <│> p2) s = let fun p2_if_fail Fail = p2 s │ p2_if_fail x = x in p2_if_fail (p1 s) end infixr 3 • fun (p modify f) s = <│> let fun modres Fail = Fail infixr 0 │ modres (Ok (x, y)) = Ok (f x, y) modify in modres (p s) end infixr 4 • fun (p1 <&> p2) s = <&> let fun p2_after Fail = Fail │ p2_after (Ok (x1, s1)) = (p2 modify (pair x1)) s1 in p2_after (p1 s) end • fun emptyseq s = Ok ([], s) • fun optional p = (p modify (consonto [])) <│> emptyseq 60 Fallstudie 3: Command Interpreter Expression Parsers (1) • fun exp s = (aexp <&> optional (literal „>“ <&> aexp) modify opt_compare) s and aexp s = (bexp <&> optional (literal „-“ <&> aexp) modify opt_sub) s and bexp s = (cexp <&> optional (literal „*“ <&> cexp) modify opt_mul) s and cexp s = ((literal „(“ <&> exp <&> literal „)“ modify unparenth) <│> (number modify Constant) <│> (variable modify Contents)) s and ... 61 Fallstudie 3: Command Interpreter Expression Parsers (2) ... and unparenth (brac, (e, ket)) = e and opt_compare (e1, [ ]) = e1 | opt_compare (e1, [ (oper, e2) ]) = Greater (e1, e2) | opt_compare other = error and opt_sub (e1, [ ]) = e1 | opt_sub (e1, [ (oper, e2) ]) = Minus (e1, e2) | opt_sub other = error and opt_mul (e1, [ ]) = e1 | opt_mul (e1, [ (oper, e2) ]) = Times (e1, e2) | opt_mul other = error 62 Fallstudie 3: Command Interpreter Command Parsers (1) • fun command s = (unitcom <&> optional (literal „;“ <&> command) modify opt_seq) s and unitcom s = (whilecom <|> ifcom <|> assign) s and whilecom s = (literal „WHILE“ <&> exp <&> literal „DO“ <&> command <&> literal „END“ modify mk_while_node) s and ifcom s = (literal „IF“ <&> exp <&> literal „THEN“ <&> command <&> literal „ELSE“ <&> command <&> literal „END“ modify mk_if_node) s and assign s = (variable <&> literal „:=„ <&> exp modify mk_assign_node) s and ... 63 Fallstudie 3: Command Interpreter Command Parsers (2) ... and opt_seq (c1, [ ]) = c1 | opt_seq (c1, [(semicol, c2)]) = Sequence(c1, c2) | opt_seq other = error and mk_while_node (w, (ex, (d, (com, e)))) = While (ex, com) and mk_if_node (i, (ex, (t, (c1, (e, (c2, f)))))) = Conditional (ex, c1, c2) and mk_assign_node (v, (coleq, e)) = Assign (v, e) 64 Abstrakte Datentypen Kunden Funktion Typ Programm ADT Operationen (Signaturen) Implementationen Darstellungen Darstellungen 65 Abstrakte Datentypen Beispiele • Store definiert via Funktionen & Konstanten type store get: variable x store → value update: store x variable x value → store nullstore: store • Set (s. Uebung) Alle Werte gleich 0 66 Abstrakte Datentypen konkret Beispiel canvas: Definition • datatype color = Red | Orange | Yellow | green | Blue | Indigo | Violet • datatype coordinate = Coord of int x int abstrakt • type canvas newcanvas: color → int → int → canvas sizecanvas: canvas → (int * int) colorof: canvas → coordinate → color paint: color → coordinate → canvas → canvas 67 Abstrakte Datentypen Beispiel canvas: Spezifikation • is_on: coordinate → canvas → bool • For all P, P': coordinate Hilfsprädikat For all col: color For all m, n, m1, n1: int For all cnv: canvas colorof (newcanvas col m n) P‘ = col colorof (paint col P cnv) P‘ = if P = P‘ & is_on (P, cnv) then col else colorof canvas P‘ sizecanvas (newcanvas col m n) = (m, n) sizecanvas (paint col P cnv) = sizecanvas cnv is_on (Coord (m1, n1), newcanvas col m n) = m1 > 0 & m1 <= m & n1 > 0 & n1 <= n is_on (P‘, paint col P cnv) = is_on (P‘, cnv) 68 Abstrakte Datentypen Beschränkter Gültigkeitsbereich des Konstruktors Cnv Beispiel canvas: 1. Implementation abstype canvas = Cnv of int x int x (coordinate → color) K col P = col with fun newcanvas col m n = Cnv (m, n, K col) fun sizecanvas (Cnv (m, n, f)) = (m, n) fun colorof (Cnv (m, n, f)) P = f P fun paint col (Coord (m1, n1)) (Cnv (m, n, f)) = if m1 > 0 & m1 <= m & n1 > 0 & n1 <= n then Cnv (m, n, assoc [(Coord (m1, n1), col)] f) else Cnv (m, n, f) end 69 Abstrakte Datentypen Beispiel canvas • Authentication local fun f (Coord (m1, n1)) = if m1 < n1 then Red else Blue in val mycanvas = Cnv (10, 10, f) end • Secrecy fun get_paint_fn (Cnv (m, n, f)) = f 70 Abstrakte Datentypen Beispiel canvas: 2. Implementation abstype canvas = Paint of color x coordinate x canvas | Newcanvas of color x int x int with local fun is_on (Coord (m1, n1), Newcanvas (col, m, n)) = m1 > 0 & m1 <= m & n1 > 0 & n1 <= n | is_on (P‘, Paint (col, P, cnv)) = is_on (P‘, cnv) in fun newcanvas col m n = Newcanvas (col, m, n) fun paint col P cnv = Paint (col, P, cnv) fun sizecanvas (Newcanvas (col, m, n)) = (m, n) | sizecanvas (Paint (col, P, cnv)) = sizecanvas cnv fun colorof (Newcanvas (col, m, n)) P = col | colorof (Paint (col, P, cnv)) P‘ = if P = P‘ & is_on(P‘, cnv) then col else colorof cnv P‘ end 71 end Abstrakte Datentypen Beispiel canvas • Die zweite Implementation von canvas widerspiegelt die Entstehungsgeschichte. Falls P1 # P2 sind folgende Konstruktionen verschiedene Darstellungen desselben abstrakten Wertes Paint (col1, P1, Paint (col2, P2, cnv)) Paint (col2, P2, Paint (col1, P1, cnv)) • Die Gleichheitsrelation für abstrakte Datenypen muss explizit implementiert werden 72 Abstrakte Datentypen Parametrisierte Typen • abstype α board = Board of int x int x coordinate → α with fun newboard b m n = if m > 0 & n > 0 then Board (m, n, K b) else error fun sizeboard (Board (m, n, f)) = (m, n) fun contentsboard (Board (m, n, f)) = if m1 > 0 & m1 <= m & n1 > 0 & n1 <= n then f (Coord (m1, n1)) else error fun updateboard (Board (m, n, f)) (Coord (m1, n1)) b if m1 > 0 & m1 <= m & n1 > 0 & n1 <= n then Board (m, n, assoc[(Coord (m1, n1), b)] f) else error end 73 Abstrakte Datentypen Subtypen • type ordintlist null_ord: ordintlist → bool nil_ord: ordintlist hd_ord: ordintlist → int tl_ord: ordintlist → ordintlist insert_ord: int → ordintlist → ordintlist order: int list → ordintlist 74 Abstrakte Datentypen Subtypen • abstype ordintlist = Ordered of int list with local fun insert n [] = [n] │insert n (a :: x) = if (lessthan a) n then n :: a :: x else a :: insert n x fun sort [] = [] | sort (a :: x) = let val low = filter (lessthan a) x and high = filter (non (lessthan a)) x in sort low @ [a] @ sort high Quicksort in fun null_ord (Ordered []) = true │ null_ord (Ordered (a :: x)) = true val nil_ord = Ordered [] fun hd_ord (Ordered (a :: x)) = a hd_ord (Ordered [] ) = error fun tl_ord (Ordered (a :: x)) = Ordered x tl_ord (Ordered []) = error fun insert_ord n (Ordered x) = Ordered (insert n x) fun order x = Ordered (sort x) end end 75 Strukturen und Funktoren Module • Struktur ¾ Namespace ¾ Menge von Definitionen ¾ Environment Komponente • Beispiel ListOps ¾ structure ListOps = struct fun foldR ... fun reduce ... fun member ... end ¾ let val accumulate = ListOps.foldR in accumulate times 2 end ¾ local open ListOps in ... end 76 Strukturen und Funktoren Signaturen z z structure B = struct datatype counter = C of int val bottom = C(0) val top = C(99) fun next (C x) = if C x = top then bottom else C (x + 1) fun above (C x) (C y) = y > x end signature SIGB = sig datatype counter = C of int val bottom: counter val top: counter val next: counter → counter val above: counter → counter → bool end 77 Strukturen und Funktoren Beispiel: Dictionary z z signature KEY = sig type key val before: key → key → bool val matches: key → key → bool end signature DICTIONARY = sig structure K: KEY type α dict val newdict: α dict val lookup: α dict → K.key → α val enter: α dict → K.key → α → α dict end 78 Strukturen und Funktoren Beispiel: Dictionary Definition • functor MkDict (Keystruct: KEY): DICTIONARY = struct structure K = Keystruct abstype α dict = Emp | Item of K.key x α x α dict x α dict with val newdict = Emp fun lookup Emp k‘ = error | lookup (Item (k, a, d1, d2)) k‘ = if K.matches k k‘ then a else if K.before k k‘ then lookup d1 k‘ else lookup d2 k‘ fun enter Emp k‘ b = Item (k‘ b, Emp, Emp) | enter (Item (k, a, d1, d2)) k‘ b = if K.matches k k‘ then Item (k‘, b, d1, d2) else if K.before k k‘ then Item (k, a, enter d1 k‘ b, d2) else Item (k, a, d1, enter d2 k‘ b) end end 79 Strukturen und Funktoren Beispiel: Dictionary Verwendung • structure IntKey = struct type key = int fun before (x: key) (y: key) = y < x fun matches (x: key) (y: key) = x = y end • structure IntDict = MkDict (IntKey) • open IntDict im aktuellen Environment ¾ structure K: KEY zur Verfügung gestellt type α dict val newdict: α dict val lookup: α dict → K.key → α → α dict ¾ wobei K = IntKey and K.key = int 80 Ausführung von Programmen • Abarbeitung von Definitionen ¾Struktur struct ¾Funktor functor ¾Signatur sig ¾Typ type Abstrakt abstype Konkret datatype ¾Wert val Funktion val fn / fun Definiert Umgebung In aktueller Umgebung • Auswertung von Ausdrücken 81 Auswertungsstrategien Lazy Evaluation • Strategien SML ¾Eager: „Vollständige Auswertung aller Argumente vor Funktionsanwendung“ ¾Lazy: „Verzögerte Auswertung der Haskell Argumente, so spät wie möglich“ • Beeinflussung des Programmierstils ¾Undefinierte Werte ¾Wiederverwenung von Komposition ¾Unendliche Datenstrukturen ¾Implizite Coroutinen 82 Auswertungsstrategien Lazy Evaluation • Bedingte Ausdrücke fun cond true x y = x | cond false x y = y Bei Lazy Evaluation cond A B false ⇔ A & B cond A true B ⇔ A | B ev. B = Ω „undefiniert“ • Rekursion fun ([] = []) = true | ((a :: x) = (b :: y)) = cond (a = b) (x = y) false | ((a :: x) = []) = false | ([] = (b :: y)) = false 83 Auswertungsstrategien Lazy Evaluation • Exists ¾Ohne Wiederverwendung fun exists p [] = false | exists p (a :: x) = if p a then true else exists p x ¾Bei Lazy Evaluation mit Wiederverwendung fun exists p x = not (null (filter p x)) 84 Auswertungsstrategien Lazy Evaluation • Sieb des Erasthotenes int list 2 3 4 ... val primes = sieve (from 2) fun sieve (a :: x) = a :: sieve (sift a x) fun sift a x = filter (non (multipleof a)) x fun multipleof a b = (b mod a = 0) 85 Auswertungsstrategien Lazy Evaluation • Ablaufsszenarium [] ← sieve ← [2, 3, 4, 5, 6, 7, 8, 9, ...] [2] ← sieve ← (sift 2) [3, 4, 5, 6, 7, 8, 9, ...] [2] ← sieve ← [3, 5, 7, 9, ...] [2, 3] ← sieve ← (sift 3) [5, 7, 9, ...] [2, 3] ← sieve ← [5, 7, ... ] [2, 3, 5] ← sieve ← (sift 5) [7, ... ] [2, 3, 5] ← sieve ← [7, ... ] [2, 3, 5, 7] ← sieve ← [... ] 86 Auswertungsstrategien Lazy Evaluation • Ablaufsmodellierung Sieve Konsument Master Sift Produzent Slave Coroutine Coroutine 87 Auswertungsstrategien Lazy Evaluation • Hamming Zahlen • 2p * 3q * 5r • val rec hamming = 1 :: merge3 (map (times 2) hamming) (map (times 3) hamming) (map (times 5) hamming) fun merge3 x y z = merge x (merge y z) fun merge (a :: x) (b :: y) = if a < b then a :: merge x (b :: y) else if a > b then b :: merge (a :: x) y else a :: merge x y 88 Auswertungsstrategien Lazy Evaluation • Ablaufsmodellierung 1 :: hamming merge3 map times 2 map times 3 hamming map times 5 89 Auswertungsstrategien Lazy Evaluation • Ablaufsszenarium [ 1, .. ] [ 1, 2, .. ] ← [ 2, .. ] [ 3, .. ] [ 5, .. ] [ 1, 2, 3, .. ] ← [ 2, 4, .. ] [ 3, .. ] [ 5, .. ] [ 1, 2, 3, 4, .. ] ← [ 2, 4, .. ] [ 3, 6, .. ] [ 5, .. ] [ 1, 2, 3, 4, 5, .. ] ← [ 2, 4, 6, .. ] [ 3, 6, .. ] [ 5, .. ] [ 1, 2, 3, 4, 5, 6, .. ] ← [ 2, 4, 6, .. ] [ 3, 6, .. ] [ 5, 10, .. ] [ 1, 2, 3, 4, 5, 6, 8, .. ] ← [ 2, 4, 6, 8, .. ] [ 3, 6, 9, .. ] [ 5, 10, .. ] [ 1, 2, 3, 4, 5, 6, 8, 9, .. ] ← [ 2, 4, 6, 8, 10, .. ] [ 3, 6, 9, .. ] [ 5, 10, .. ] • Prinzip [ .., 2a*3b*5c, .., 2p*3q* 5r, .., 2s*3t*5r ] bereits erzeugt Wähle nächstes Element aus 2a+1*3b*5c, 2p*3q+1* 5r, 2s*3t*5r+1 90 Auswertungsstrategien Funktionen als Coroutinen g a f b f (g a, a, b) c p g a f b let fun h x = f (g x, x, b) in h a end c g p b f let val rec a = p (a, c) in a end 91 let val rec a = p (a, c) in f (g a, a, b) end Auswertungsstrategien Lazy Dictionary • Aufgabe: Durchkämmen eines Textes und Annotieren aller Verwendungen von Begriffen durch deren Erklärung • Vorgehen: Laufende Erstellung bzw. Abfrage einer Tabelle bestehend aus Einträgen der Form (Begriff, Erklärung) • Problem: Begriffe, die (textuell) vor ihrer Erklärung verwendet werden 92 Auswertungsstrategien Lazy Dictionary Definition • Dictionary ¾ α dictop Operationen Entry und Lookup α dict Registratur von Paaren key x α dictop Strom • Prozess ¾ fun dictproc opstream = let val finaldict = builddict (getentries opstream) in map (lookup finaldict) (getlookups opstream) end • Signaturen ¾ dictproc: (α dictop) list → α list getentries: (α dictop) list → (key x α) list getlookups: (α dictop) list → key list builddict: (key x α) list → α dict lookup: α dict → key → α 93 Auswertungsstrategien α dictop Implementation • type key = int • datatype α dictop = Entry of (key, α) | Lookup of key • fun getentries (Lookup k :: r) = getentries r | getentries (Entry (k, a) :: r) = (k, a) :: getentries r • fun getlookups (Lookup k :: r) = k :: getlookups r | getlookups (Entry (k, a) :: r) = getlookups r 94 Auswertungsstrategien α dict Implementation • datatype α dict = Emp | Item of (key x α x α dict x α dict) • fun lookup Emp k‘ = error | lookup Item (k, a, d1, d2) k‘ = if k = k‘ then a else if k > k‘ then lookup d1 k‘ else lookup d2 k‘ • fun builddict [] = Emp | builddict ((k1, a1) :: r) let fun smaller (k, a) = k < k1 fun larger (k, a) = k > k1 in Item (k1, a1, builddict (filter smaller r), builddict (filter larger r)) end 95 Auswertungsstrategien Lazy Dictionary Illustration • opstream = [ L3, E(1, „x“), E(3, „z“), L1, L2, E(2, „y“) ] • dictproc opstream = = map (lookup finaldict) (getlookups opstream) = = map (lookup finaldict) (3 :: getlookups (E(1, “x“) :: ...)) = (lookup finaldict 3) :: (map (lookup finaldict) (getlookups (E(1, „x“) :: ...))) • finaldict = builddict ((1,“x“)::(3,“z“)::...)) = Item(1, “x“, builddict..., builddict (3,“z“)::...) = Item(1, „x“, builddict..., Item(3, „z“, ..., ...)) • lookup finaldict 3 = lookup (Item(1, „x“, builddict..., Item(3, „z“, ..., ...))) 3 = „z“ • dictproc opstream = „z“ :: map ... 96 • dictproc opstream = [ „z“, „x“, „y“ ] Auswertungsstrategien Interaktive Programme • type input = char list list Ungelesene • type output = char list list Inputdaten • type (α, β) interaction = (input x α) → (input x β x output) • <@>: (α, β) interaction x (β, γ) interaction → (α, γ) interaction infix <@> fun (i1 <@> i2) (input, a) = let val (in1, b, out1) = i1 (input, a) val (in2, c, out2) = i2 (in1, b) in (in2, c, out1 @ out2) end 97 Logische Programmierung 98 Logische Programmierung Situierung • Logische Deduktion mit Formeln erster Ordnung (Kowalski (1979) • Beweise werden via Resolution auf der Basis des Unifikationsalgorithmus automatisch erzeugt • Sprache Prolog 99 Logische Programmierung Ziel IF Horn Klauseln • A :- A1, A2, ... , An. Regel A. :- TRUE, Fakt • isappendof (X, Y, Z) ⇔ X @ Y = Z isappendof ([], X, X). Relation isappendof (A :: X, Y, A :: Z) :- isappendof (X, Y, Z). • isflattenof isflattenof (Empty, []). AND isflattenof (Tr (T1, A, T2), Z) :- isflattenof (T1, X1), isflattenof (T2, X2), isappendof (X1, A :: X2, Z). OR isflattenof (Tr (T1, A, T2), Z) :- isflattenof (T1, X1), isflattenof (T2, X2), isappendof (A :: X1, X2, Z). 100 Logische Programmierung Programme • isappendof ([1, 2], [3], [])? Logische no Variable • isappendof ([1, 2], [3], ?Z)? z = [1, 2, 3] • isappendof (?X, ?Y, [1, 2, 3])? (1) X = [], Y = [1, 2, 3] (2) X = [1], Y = [2, 3] (3) X = [1, 2], Y = [3] (4) X = [1, 2, 3], Y = [] 101 Logische Programmierung Illustration einer Deduktion • Notation Cons(1, Cons(2, Cons(3, []))) für [1, 2, 3] Ziel • Deduktion ? isappendof (Cons (?X, []), ?Y, Cons (1, Cons (2, []))) isappendof (Cons (?1, ?2), ?3, Cons (?1, ?4)) :isappendof (?2, ?3, ?4) Unifikation ?X zu 1, ?2 zu [], ?3 zu ?Y, ?1 zu 1, ?4 zu Cons (2, []) ? isappendof ([], ?Y, Cons (2, [])) Neues Ziel isappendof ([], ?5, ?5) ?Y zu Cons (2, []), ?5 zu Cons (2, []) ?X = 1, ?Y = Cons (2, []) 102 Antwort Logische Programmierung Beispiel Stammbaum (1) ht tp man (adam). man (peter). Fakten man (paul). woman (marry). woman (eve). Werte parent (adam, peter). parent (eve, peter). parent (adam, paul). parent (marry, paul). :/ /k ti .m s. m . ff cu ni ~ z/ .c ba a rt k/ ol pr og /g l ea en og y. ht l m 103 Logische Programmierung Beispiel Stammbaum (2) Variablen father (F, C) :- man (F), parent (F,C). mother (M, C) :- woman (M), parent (M,C). is_father (F) :- father (F, _). Regeln is_mother (M) :- mother (M, _). ?- father (X, paul). Anonyme X = adam Variable Abfrage, Query 104 Logische Programmierung Beispiel Stammbaum (3) son (S,P) :- man (S), parent (P, S). daughter (D, P) :- woman (D), parent (P, D). siblings (A, B) :- parent (P, A), parent (P, B), A\=B. full_siblings (A, B) :- parent (F, A), parent (F, B), parent (M, A), parent (M, B), A\=B, F\=M. full_siblings2 (A,B) :- father (F, A), father (F, B), mother (M, A), mother (M, B), A\=B. uncle (U, N) :- man (U), siblings (U, P), parent (P, N). aunt (A, N) :- woman (A), siblings (A, P), parent (P, N). grand_parent (G,N) :- parent (G, X), parent (X, N). 105 Logische Programmierung Beispiel Stammbaum (4) human(H) :- man(H). OR human(H) :- woman(H). descendent(D, A) :- parent(A, D). descendent(D, A) :- parent(P, D), descendent(P, A). ancestor(A, D) :- descendent(D, A). 106 Logische Programmierung Beispiel Fakultät (1) • factorial(0,1). factorial(N,F) :- N>0, N1 is N-1, factorial(N1,F1), F is N * F1. ?- factorial(3,W). W=6 factorial(3, 6) Klausel baum 3>0 2 is 3-1 factorial(2, 2) 6 is 3*2 2>0 1 is 2-1 factorial(1, 1) 2 is 2*1 1>0 0 is 1-1 factorial(0, 1) 1 is 1*1 true 107 Logische Programmierung Beispiel Fakultät (2) • Ableitungsbaum Trace ?- factorial(3,X). (1) 0 Call: factorial(3,_8140) ? (1) 1 Head [2]: factorial(3,_8140) ? (2) 1 Call (built-in): 3>0 ? (2) 1 Done (built-in): 3>0 ? (3) 1 Call (built-in): _8256 is 3-1 ? (3) 1 Done (built-in): 2 is 3-1 ? (4) 1 Call: factorial(2, _8270) ? ... (1) 0 Exit: factorial(3,6) ? X=6 108 Logische Programmierung Beispiel Türme von Hanoi (1) • move(1, X, Y, _) :write('Move top disk from '), write(X), write(' to '), write(Y). move(N, X, Y, Z) :N>1, M is N-1, move(M, X, Z, Y), move(1, X, Y,_), move(M, Z, Y, X). 109 Logische Programmierung Beispiel Türme von Hanoi (2) • ?- move(3,left,right,center). Move top disk from left to right Move top disk from left to center Move top disk from right to center Move top disk from left to right Move top disk from center to left Move top disk from center to right Move top disk from left to right yes 110 Logische Programmierung Beispiel Türme von Hanoi (3) • zum Erreichen des Ziels ?- move(3, left, right, center) • erreiche Ziel ?-move(2, left, center, right) danach erreiche Ziel ?-move(1, left, right, center) danach erreiche Ziel ?-move(2, center, right, left). 111 Logische Programmierung Deduktionsstrategie (1) • /* program P p(a). p(X) :- q(X), r(X). p(X) :- u(X). q(X) :- s(X). r(a). r(b). s(a). s(b). s(c). u(d). clause # */ /* #1 */ /* #2 */ /* #3 */ /* #4 */ /* #5 */ /* #6 */ /* #7 */ /* #8 */ /* #9 */ /* #10 */ 112 Logische Programmierung Deduktionsstrategie (2) • Klauselbäume p(a) p(b) p(c) p(d) true q(b) r(b) q(c) r(c) u(d) s(b) true s(c) true true true 113 Logische Programmierung Deduktionsstrategie (3) • ?- p(X) X = a X = b X = d Depth-First Traversierung Unifikation 114 Logische Programmierung „!“ (cut) als Steuerbefehl • havevisitor(friday). weather(friday, fair). Falltüre, weather(saturday, fair). blockiert das weather(sunday, fair). Backtracking weekend(saturday). weekend(sunday). picnic(Day) :- weather(Day, fair), !, weekend(Day)., ! picnic(Day) :- havevisitor(Day). • ?- picnic(When) ?- picnic(When) When = saturday no When = sunday ?- picnic(When) When = friday When = saturday „red cuts“ yes yes 115 Logische Programmierung Negation als Failure Negation „Q wenn nicht P“ ¾ Q :- P, !, fail. Notation für Q Q. \+ P ¾ different(X, Y) :- X=Y, !, fail. different(X, Y). ¾ home(X) :- out(X), !, fail. home(X). out(sue). ?- home(sue) closed world no assumption ?- home(joe) ?- home(Anyone) 116 Logische Programmierung Negation als Failure student(bill). student(joe). married(joe). single_student(X) :- (\+ married(X)), student(X). ?- single_student(bill) yes ?- single_student(joe) no ?- single_student(X) no single_student(X) :- student(X), (\+ married(X)) ?- single_student(X) X = bill 117 Logische Programmierung Alternative • Bedingung „Wenn P dann Q sonst R“ ¾S :- P, !, Q. S :- R. ¾add(X, L1, L2) :- member(X, L1), !, L2 = L1. add(X, L1, L2) :- L2 = [X| L1]. Durch Hinzufügen von X zu L1 entsteht L2 118 Logische Programmierung Zustandsübergänge • The Hungry Monkey There is a monkey at the door into a room. In the middle of the room a banana is hanging from the ceiling. The monkey is hungry and wants to get the banana, but he cannot stretch high enough from the floor. At the window of the room there is a box that the monkey can use. The monkey can perform the following actions: walk on the floor, climb the box, push the box around (if he is already at it), and grasp the banana if he is standing on the box and directly underneath the banana. Can the monkey grasp the banana? 119 Logische Programmierung Zustandsübergänge • Zustand des Systems allgm state(M, B, O, G). Anfang state(door, window, onfloor, hasnot). Ende state(_, _, _, has) • Aktionen walk(P1, P2) push(P1, P2) climb grab 120 Logische Programmierung Zustandsübergänge • Perform Action ¾perform(A, S1, S2) ¾perform(grasp, state(middle, middle, onbox, hasnot), state(middle, middle, onbox, has)). perform(climb, state(MP, BP, onfloor, H), state(BP, BP, onbox, H)). perform(push(P1, P2), state(P1, P1, onfloor, H), state(P2, P2, onfloor, H)). perform(walk(P1, P2), state(P1, BP, onfloor, H), state(P2, BP, onfloor, H)). 121 Logische Programmierung Zustandstransformation • Get Food getfood(state(_, _, _, has)). getfood(S1) :- perform(A, S1, S2), getfood(S2). • Query ?- getfood(state(atdoor, atwindow,onfloor, hasnot)). yes. 122 Logische Programmierung Zustandstransformation • Mit Trace Output getfood(S1) :perform(A, S1, S2), nl, write(‚in '), write(S1), nl, write(' try '), write(A), getfood(S2). 123 Logische Programmierung Zustandstransformation • in state(atdoor, atwindow, onfloor, hasnot) try climb in state(atdoor, atwindow, onfloor, hasnot) try walk(atdoor, _224) in state(_224, atwindow, onfloor, hasnot) try climb in state(atwindow, atwindow, onfloor, hasnot) try push(atwindow, _283) in state(_283, _283, onfloor, hasnot) try climb in state(middle, middle, onbox, hasnot) try grasp yes 124 Logische Programmierung Digitale Schaltkreise • Logischer Operator → Prolog Prädikat ¾ INVERTER inv(0, 1), inv(1, 0) ¾ AND Gate and(0, 0, 0), and(0, 1, 0), and(1, 0, 0), and(1, 1, 1) • Schaltkreis → Prolog Regel Circuit (Input, Output) :Gate1 (InputA, InputB, OutputC), ... GateN (InputA, InputB, OutputC). • Schaltkreissimulation → Prolog Query ?- Circuit (Input, Output) 125 Logische Programmierung Digitale Schaltkreise A B T1 E C D T2 Circuit (A, B, C, D, E) :NAND (A, B, T1), NORE (C, D, T2), NAND (T1, T2, E). ?- Circuit (A, B, C, D, E) 126 Fallstudie 1: Eliza Weizenbaum 1966, nach Sterling & Shapiro run :nl, write('What is your problem?'), nl, write('>> '), read_word_list(Input), eliza(Input), !. eliza([bye]) :nl, write('Goodbye. I hope I have helped you.'), nl. eliza(Input) :Create pattern(Stimulus, Response), Dictionary match(Stimulus, Dictionary, Input), match(Response, Dictionary, Output), Create reply(Output), Output read_word_list(Input1), !, eliza(Input1). reply([Head|Tail]) :- write(Head), write(' '), reply(Tail). reply([]) :- nl, write('>> '), !. 127 Fallstudie 1: Eliza Korrespondierende Musterpaare pattern([i, am, 1], [how, long, have, you, been, 1, ?]). pattern([1, you, 2, me, 3], [what, makes, you, think, i, 2, you, ?]). pattern([i, like, 1], [does, anyone, else, in, your, family, like, 1, ?]). pattern([i, feel, 1], [do, you, often, feel, that, way, ?]). pattern([1, love, 2], [do, you, feel, unloved, ?]). pattern([1, X, 2], [can, you, tell, me, more, about, your, X, ?]) :important(X). pattern([1, me], [what, makes, you, think, that, ?]). pattern([1], [please, tell, me, more]). important(father). important(mother). important(problem). important(fear). 128 Fallstudie 1: Eliza Pattern Matching with I/O Creation Stimulus Dictionary Input Response Dictionary Output match([N| Pattern], Dictionary, Target) :integer(N), lookup(N, Dictionary, LeftTarget), append(LeftTarget, RightTarget, Target), match(Pattern, Dictionary, RightTarget). match([Word| Pattern], Dictionary, [Word| Target]) :atom(Word), match(Pattern, Dictionary, Target). match([], _, []). lookup(Key, [(Key, Value)| Tail], Value). lookup(Key, [(Key1, _)| Tail], Value) :\+ (Key = Key1), lookup(Key, Tail, Value). 129 Fallstudie 1: Eliza Pattern Matching with I/O Creation • match ([i, am, 1], beim Dictionary, Aufruf [i, am, sick]) • match ([i, am, 1], beim [(1, [sick])| Tail], Austritt [i, am, sick]) • match ([how, long, have, you, been, 1, ?], [(1, [sick])| Tail], Output) • match ([how, long, have, you, been, 1, ?], [(1, [sick])| Tail], [how, long, have, you, been, sick, ?]) Stimulus Dictionary Input Stimulus Dictionary Input Response Dictionary Output Response Dictionary Output 130 Fallstudie 1: Eliza Input Scanning Support read_word_list(Ws) :- get0(C), read_word_list(C, Ws). read_word_list(C, [W|Ws]) :word_char(C, C1), read_word(C1, W, C2), read_word_list(C2, Ws). read_word_list(C, []) :- end_of_words_char(C). read_word_list(C, Ws) :fill_char(C), get0(C1), read_word_list(C1, Ws). read_word(C, W, C1) :word_chars(C, Cs, C1), name(W, Cs). word_chars(C, [C1| Cs], C0) :word_char(C, C1), !, get0(C2), word_chars(C2, Cs, C0). word_chars(C, [], C) :- \+ word_char(C, _). 131 Fallstudie 1: Eliza Input Scanning Support word_char(C, C) :- 97 =< C, C =< 122. word_char(C, C1) :- 65 =< C, C =< 90, C1 is C + 32. word_char(C, C) :- 48 =< C, C =< 57. word_char(95, 95). % _ word_char(39, 39). % ' fill_char(32). % space fill_char(40). % ( fill_char(41). % ) fill_char(33). % ! fill_char(63). % ? fill_char(_). % treat any other "bad" char as fill char end_of_words_char(46). % . end_of_words_char(10). % newline 132 Fallstudie 2: Flucht über Brücke Hilfsprädikate (Lösung nach Ch. Portmann) • append1 ([], L, L). append1 ([X|L1], L, [X|L2]) :append1 (L1, L, L2). • select1 (X, [X|L], L). select1 (X, [Y|L1], [Y|L2]) :select1 (X, L1, L2). • group ([X], L1, L2, X) :- select1 (X, L1, L2). X Maximum Y group ([X, Y], L1, L2, Y) :select1 (X, L1, L), select1 (Y, L, L2), X <= Y. 133 Fallstudie 2: Flucht über Brücke Zyklus left → right → left Protokoll • left (L, R, P0, P2, T0, T2, TMax) :group (X, L, L1, TGroup), T0 append1 (X, R, R1), L append1 (P0, [X], P1), T2 T1 is T0 + TGroup, T1 =< TMax, right (L1, R1, P1, P2, T1, T2, TMax). T1 R 134 Fallstudie 2: Flucht über Brücke Zyklus right → left → right • right (L, R, P0, P2, T0, T2, TMax) :group (X, R, R1, TGroup), append1 (X, L, L1), append1 (P0, [X], P1), T1 is T + TGroup, T1 =< TMax, left (L1, R1, P1, P2, T1, T2, TMax). • right([], _, P, P, T, T, _). Ziel 135 Fallstudie 2: Flucht über Brücke Programm • go (People, TMax, P, T) :left (People, [], [], P, 0, T, TMax). • go ([5, 10, 20, 25], 60, P, T). start (people coded by transition time) 136 Deskriptive Programmierung 137 XML (Extended Markup Language) • XML Elemente Taginhalt Sematisches <director>John Doe</director> Tag <actor>John Doe</actor> <CITY zip="4000">Basel</CITY> Mit Attribut <marker kind= "separator" /> Leeres Tag • XML Dokumente <?xml version="1.0" encoding="ISO-8859-1"?> <library> <book isbn="0345374827"> <title>Zen and the Art of Motorcycle Maintenance </title> <author>Robert M. Pirsig</author> </book> 138 </library> XML Namespaces • Explizite Namespaces Globally unique id <LIBRARY> <books:BOOK xmlns:books="urn:BookLovers.org:BookInfo" xmlns:money="urn:Finance:Money"> <books:TITLE>Creepy Crawlies</books:TITLE> <books:PRICE money:currency="US Dollar"> 22.95 </books:PRICE> </books:BOOK> </LIBRARY> • Default Namespace <BOOK xmlns="urn:BookLovers.org:BookInfo"> <TITLE>Creepy Crawlies</TITLE> <PRICE currency="US Dollar">22.95</PRICE> </BOOK> 139 XML Schemata (1) • <?xml version="1.0"?> <note xmlns="http://www.w3schools.com" xmlns:xsi= "http://www.w3.org/2001/XMLSchemainstance" xsi:schemaLocation= "http://www.w3schools.com/schema/note.xsd"> <to>Tove</to> <from>Jani</from> <heading>Reminder</heading> <body lang="EN">Don't forget me!</body> </note> 140 XML Schemata (2) • <?xml version="1.0"?> <xs:schema xmlns="http://www.w3schools.com" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.w3schools.com" elementFormDefault="qualified"> <xs:element name="note"> complex <xs:complexType><xs:sequence> simple <xs:element name="to" type="xs:string"/> <xs:element name="from" type="xs:string"/> <xs:element name="heading" type="xs:string"/> <xs:element name="body" mixed="true"> <xs:attribute name="lang" type="xs:string"/> </xs:element> El./Attr. </xs:sequence></xs:complexType> </xs:element> und Text 141 </xs:schema> Schemata Modifiers • Defaultwert-Modifiers <xs:element name="color" type="xs:string" default="red"/> <xs:element name="color" type="xs:string" fixed="red"/> • Bereich-Modifiers <xs:element name="age"> <xs:simpleType> <xs:restriction base="xs:integer"> <xs:minInclusive value="0"/> <xs:maxInclusive value="100"/> </xs:restriction> </xs:simpleType> </xs:element> 142 Schemata Modifiers • Bereich-Modifiers ¾ <xs:element name="car"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:enumeration value="Audi"/> <xs:enumeration value="Golf"/> <xs:enumeration value="BMW"/> </xs:restriction> </xs:simpleType> </xs:element> ¾ <xs:element name="letter"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:pattern value="([a-z])*"/> </xs:restriction> </xs:simpleType> </xs:element> 143 Schemata Typdefinition • <xs:complexType name="personinfo"> <xs:sequence> <xs:element name="firstname" type="xs:string"/> <xs:element name="lastname" type="xs:string"/> </xs:sequence> </xs:complexType> • <xs:element name="employee" type="personinfo"/> <xs:element name="student" type="personinfo"/> <xs:element name="member" type="personinfo"/> 144 Schemata Typableitung durch Erweiterung • <xs:complexType name="personinfo"> <xs:sequence> <xs:element name="firstname" type="xs:string"/> <xs:element name="lastname" type="xs:string"/> </xs:sequence> </xs:complexType> • <xs:complexType name="fullpersoninfo"> <xs:complexContent> <xs:extension base="personinfo"> <xs:sequence> <xs:element name="address" type="xs:string"/> <xs:element name="city" type="xs:string"/> <xs:element name="country" type="xs:string"/> </xs:sequence></xs:extension> </xs:complexContent> </xs:complexType> • <xs:element name="employee" type="fullpersoninfo"/> 145 Schemata Typableitung durch Einschränkung • <xs:complexType name="vehicle"> <xs:complexContent> <xs:sequence> <xs:element name="license" type="xs:string"/> <xs:element name="category" type="xs:string"/> <xs:element name="fabdate" type="xs:date"/> <xs:element name="weight" type="xs:int"/> </xs:sequence> </xs:complexContent> </xs:complexType> • <xs:complexType name="bicycle"> <xs:restriction base="personinfo"> <xs:sequence> <xs:element name="license" type="xs:string"/> <xs:element name="fabdate" type="xs:date"/> </xs:sequence> </xs:restriction> </xs:complexType> 146 Schemata Kompositoren Alle in beliebiger Reihenfolge • <xs:element name="person"> <xs:complexType> <xs:all> <xs:element name="firstname" type="xs:string"/> <xs:element name="lastname" type="xs:string"/> </xs:all> </xs:complexType> Genau </xs:element> eines • <xs:element name="person"> <xs:complexType> <xs:choice> <xs:element name="employee" type="employee"/> <xs:element name="member" type="member"/> </xs:choice> </xs:complexType> </xs:element> 147 Schemata Kompositoren Genau in dieser Reihenfolge • <xs:element name="person"> <xs:complexType> <xs:sequence> <xs:element name="firstname" type="xs:string"/> <xs:element name="lastname" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> • <xs:element name="person"> <xs:complexType> <xs:sequence> <xs:element name="full_name" type="xs:string"/> <xs:element name="child_name" type="xs:string" maxOccurs="10" minOccurs="0"/> </xs:sequence> </xs:complexType> Spezifikation der Anzahl </xs:element> 148 Schemata Any Element Auszug aus familiy.xsd • <xs:element name="person"> <xs:complexType> <xs:sequence> <xs:element name="firstname" type="xs:string"/> <xs:element name="lastname" type="xs:string"/> <xs:any minOccurs="0"/> </xs:sequence> </xs:complexType> </xs:element> • <xs:element name="children"> <xs:complexType> <xs:sequence> <xs:element name="childname" type="xs:string" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> Auszug aus children.xsd 149 • <?xml version="1.0" encoding="ISO-8859-1"?> <persons xmlns="http://www.microsoft.com" xmlns:xsi= "http://www.w3.org/2001/XMLSchema instance" xsi:SchemaLocation= "http://www.microsoft.com family.xsd http://www.w3schools.com children.xsd"> <person> <firstname>Hege</firstname> <lastname>Refsnes</lastname> <children> <childname>Cecilie</childname> </children> </person> <person> <firstname>Stale</firstname> <lastname>Refsnes</lastname> </person> </persons> 150 Schemata Elementgruppen • <xs:group name="persongroup"> <xs:sequence> <xs:element name="firstname" type="xs:string"/> <xs:element name="lastname" type="xs:string"/> <xs:element name="birthday" type="xs:date"/> </xs:sequence> </xs:group> • <xs:element name="person" type="personinfo"> • <xs:complexType name="personinfo"> <xs:sequence> <xs:group ref="persongroup"/> <xs:element name="country" type="xs:string"/> </xs:sequence> </xs:complexType> 151 Schemata Attributgruppen • <xs:attributeGroup name="personattrgroup"> <xs:attribute name="firstname" type="xs:string"/> <xs:attribute name="lastname" type="xs:string"/> <xs:attribute name="birthday" type="xs:date"/> </xs:attributeGroup> • <xs:element name="person"> <xs:complexType> <xs:attributeGroup ref="personattrgroup"/> </xs:complexType> </xs:element> 152 XML Baumsicht & Pfadmodell • XPath Notation für XML Knotenzugriffe XML Baum <AAA> <BBB/> <CCC/> <BBB/> <BBB/> <DDD> <BBB/> </DDD> <CCC/> </AAA> Knotenidentifikation durch Pfade /AAA /AAA/CCC /AAA/DDD/BBB 153 <AAA> <BBB/> <CCC/> <BBB/> <DDD> <BBB/> </DDD> <CCC> <DDD> <BBB/> <BBB/> </DDD> </CCC> </AAA> <AAA> <BBB/> <CCC/> <BBB/> <DDD> <BBB/> </DDD> <CCC> <DDD> <BBB/> <BBB/> </DDD> </CCC> </AAA> //BBB //DDD/BBB 154 <AAA> <AAA> <XXX> <XXX> <DDD> <DDD> <BBB/> <BBB/> <BBB/> <BBB/> <EEE/> <EEE/> <FFF/> <FFF/> </DDD> </DDD> </XXX> </XXX> <CCC> <CCC> <DDD> <DDD> <BBB/> <BBB/> <BBB/> <BBB/> <EEE/> <EEE/> <FFF/> <FFF/> </DDD> </DDD> </CCC> </CCC> <CCC> <CCC> <BBB> <BBB> <BBB> <BBB> <BBB/> <BBB/> </BBB> </BBB> </BBB> </BBB> </CCC> </CCC> </AAA> </AAA> /AAA/CCC/DDD/* /*/*/*/BBB //* (alle) 155 <AAA> <BBB/> <BBB/> <BBB/> <BBB/> </AAA> <AAA> <BBB id = "b1"/> //BBB[@*] <BBB id = "b2"/> <BBB name = "bbb"/> //BBB[not(@*)] <BBB/> </AAA> /AAA/BBB[1] /AAA/BBB[last] //@id //BBB[@id] //BBB[@name] 156 <AAA> <AAA> <BBB id = "b1"/> <BBB id = "b1"/> <BBB name = " bbb "/> <BBB name = " bbb "/> <BBB name = "bbb"/> <BBB name = "bbb"/> </AAA> </AAA> //BBB[@id='b1'] //BBB[@name='bbb'] //BBB[normalize-space(@name)='bbb'] 157 <AAA> <CCC> <BBB/> <BBB/> <BBB/> </CCC> <DDD> <BBB/> <BBB/> </DDD> <EEE> <CCC/> <DDD/> </EEE> </AAA> <AAA> <CCC> <BBB/> <BBB/> <BBB/> </CCC> <DDD> <BBB/> <BBB/> </DDD> <EEE> <CCC/> <DDD/> </EEE> </AAA> //*[count(BBB)=2] //*[count(*)=2] //*[count(*)=3] <AAA> <CCC> <BBB/> <BBB/> <BBB/> </CCC> <DDD> <BBB/> <BBB/> </DDD> <EEE> <CCC/> <DDD/> </EEE> </AAA> 158 <AAA> <BCC> <BBB/> <BBB/> <BBB/> </BCC> <DDB> <BBB/> <BBB/> </DDB> <BEC> <CCC/> <DBD/> </BEC> </AAA> <AAA> <BCC> <BBB/> <BBB/> <BBB/> </BCC> <DDB> <BBB/> <BBB/> </DDB> <BEC> <CCC/> <DBD/> </BEC> </AAA> <AAA> <BCC> <BBB/> <BBB/> <BBB/> </BCC> <DDB> <BBB/> <BBB/> </DDB> <BEC> <CCC/> <DBD/> </BEC> </AAA> //*[name()='BBB'] //*[starts-with(name(),'B')] //*[contains(name(),'C')] 159 <AAA> <Q/> <SSSS/> <BB/> <CCC/> <DDDDDDDD/> <EEEE/> </AAA> //*[string-length(name()) = 3] //*[string-length(name()) < 3] //*[string-length(name()) > 3] 160 <AAA> <AAA> <AAA> <BBB/> <BBB/> <BBB/> <CCC/> <CCC/> <CCC/> <DDD> <DDD> <DDD> <CCC/> <CCC/> <CCC/> </DDD> </DDD> </DDD> <EEE/> <EEE/> <EEE/> </AAA> </AAA> </AAA> //CCC | //BBB /AAA/EEE | //BBB /AAA/EEE | //DDD/CCC | /AAA | //BBB 161 <AAA> <BBB/> <BBB/> <BBB/> <BBB/> <BBB/> <BBB/> <BBB/> <BBB/> <CCC/> <CCC/> <CCC/> </AAA> <AAA> <BBB/> <BBB/> <BBB/> <BBB/> //BBB[position() mod 2 = 0] <BBB/> //BBB[ position() = floor(last() div 2 + 0.5) or <BBB/> position() = ceiling(last() div 2 + 0.5)] <BBB/> <BBB/> //CCC[ position() = floor(last() div 2 + 0.5) or <CCC/> position() = ceiling(last() div 2 + 0.5)] <CCC/> <CCC/> </AAA> 162 / ... :: Achse Achsen self child (Default) descendant parent ancestor following-sibling preceding-sibling following preceding descendant-or-self ancestor-or-self Partitionierung children, children of children, ... parents, parents of parents, ... following siblings preceding siblings Bezüglich aktuellem context 163 <AAA> <BBB> <AAA> <CCC/> <BBB> <BBB/> <ZZZ> <CCC/> <CCC/> <DDD/> <DDD/> </AAA> </ZZZ> </BBB> </BBB> <XXX> /AAA <XXX> <DDD> /child::AAA <DDD> <EEE/> /AAA/BBB <EEE/> <DDD/> /child::AAA/child::BBB <DDD/> <CCC/> /child::AAA/BBB <CCC/> <FFF/> <FFF/> <FFF> <FFF> <GGG/> <GGG/> </FFF> </FFF> </DDD> </DDD> </XXX> //CCC/following-sibling::* </XXX> <CCC> //GGG/preceding::* <CCC> <DDD/> <DDD/> </CCC> </CCC> </AAA> 164 </AAA> <AAA> XSLT Grundprinzipien • Transformiert XML Quellbaum in XML Resultatbaum Typische Anwendung ist die Darstellung eines XML Quelldokumentes in Form eines XHTML Resultatdokumentes • Ist regelbasiert. Erkennt spezifizierte Templates im Quellbaum und transformiert sie gemäss angegebenen Regeln • Transformiert den Restbaum identisch • Verwendet XPath zur Navigation im XML Baum 165 XSLT Beispiel CD Katalog • <?xml version="1.0" encoding="ISO-8859-1"?> <catalog> <cd> <title>Empire Burlesque</title> <artist>Bob Dylan</artist> <country>USA</country> <company>Columbia</company> <price>10.90</price> <year>1985</year> </cd> ... </catalog> 166 Schablone • <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> XPath (root) <html> <body> <h2>My CD Collection</h2> <table border="1"> <tr bgcolor="#9acd32"> <th align="left">Title</th> <th align="left">Artist</th> XPath </tr> <xsl:for-each select="catalog/cd"> <tr> <td><xsl:value-of select="title"/></td> <td><xsl:value-of select="artist"/></td> </tr> </xsl:for-each> Schreibe </table> operation </body> </html> </xsl:template> </xsl:stylesheet> 167 XSLT Output Steuerung • XPath Funktionen o Anzahl Knoten Review of 3.5 = <xsl:value-of select="count(books/book[review=3.5])"/> o Wert als Zahl The number is: <xsl:value-of select="number(books/book/price)"/> o Substring <xsl:value-of select="substring(name, 1, 3)"/> o Position im Kontext <xsl:number value="position()"/>. <xsl:value-of select="name"/> o Summe Total Price = <xsl:value-of select="sum(//price)"/> 168 XSLT Output Steuerung • Sortieren o <xsl:sort select = string-expression data-type = { "text" | "number" | Qname } order = { "ascending" | "descending" } case-order = { "upper-first" | "lower-first" } lang = { language-code } /> o <xsl:for-each select="catalog/cd"> <xsl:sort select="artist"/> <tr> <td><xsl:value-of select="title"/></td> <td><xsl:value-of select="artist"/></td> </tr> </xsl:for-each> 169 XSLT Output Steuerung • Bedingung <xsl:for-each select="catalog/cd"> <xsl:if test="price&gt;10"> <tr> <td><xsl:value-of select="title"/></td> <td><xsl:value-of select="artist"/></td> </tr> </xsl:if> </xsl:for-each> • Filter <xsl:for-each select="catalog/cd[artist='...']"> Filteroperatoren = (equal) != (not equal) &lt; &gt;170 XSLT • Auswahl Output Steuerung <xsl:for-each select="catalog/cd"> <tr> <td><xsl:value-of select="title"/></td> <xsl:choose> <xsl:when test="price&gt;'10'"> <td bgcolor="#ff00ff"> <xsl:value-of select="artist"/> </td> </xsl:when> <xsl:otherwise> <td><xsl:value-of select="artist"/></td> </xsl:otherwise> </xsl:choose> </tr> </xsl:for-each> 171 XSLT Output Steuerung • Hinzufügen eines Attributes <img> <xsl:attribute name="src"> <xsl:value-of select="@src" /> </xsl:attribute> </img> 172 XSLT Output Steuerung • Anwendung von Templates Regelbasierte Architektur <xsl:template match="/"> <html> <body> <h2>My CD Collection</h2> <xsl:apply-templates/> </body> </html> </xsl:template> <xsl:template match="cd"> <p> <xsl:apply-templates select="title"/> <xsl:apply-templates select="artist"/> </p> </xsl:template> 173 XSLT Output Steuerung • Anwendung von Templates <xsl:template match="title"> Title: <span style="color:#ff0000"> <xsl:value-of select="."/> </span> <br /> </xsl:template> <xsl:template match="artist"> Artist: <span style="color:#00ff00"> <xsl:value-of select="."/> </span> <br /> </xsl:template> 174 Simple Vector Graphics (SVG) Beispiel 1 • Blaues Rechteck in rotem Rechteck <?xml version="1.0" encoding="ISO-8859-1" standalone="no" ?> <!DOCTYPE svg PUBLIC "//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/ REC-SVG 20010904/DTD/svg10.dtd"> <svg width="200" height="200" xmlns="http://www.w3.org/2000/svg"> <rect x="0" y="0" width="200" height="200" style="fill:red;" /> <svg x="10" y="10" width="100" height="100"> <rect x="0" y="0" width="100" height="100" style="fill:blue;" /> </svg> </svg> 175 Simple Vector Graphics (SVG) • Spirale als Pfad Beispiel 2 • <path d="M156 334 C153.239 334 151 334 151 334 C151 339.523 153.239 344 156 344 C164.284 344 171 339.523 171 334 C171 322.954 164.284 314 156 314 C142.193 314 131 322.954 131 334 C131 350.568 142.193 364 156 364 C175.33 364 191 350.568 191 334 C191 311.909 175.33 294 156 294 C131.147 294 111 311.909 111 334 C111 361.614 131.147 384 156 384 C186.375 384 211 361.614 211 334 C211 300.863 186.375 274 156 274" style="fill:none;stroke:url(#red-darkgreen); stroke-width:2"/> • M = moveto, L = lineto, H = horizontal lineto, V = vertical lineto, C = curveto, S = smooth curveto, Q = quadratic bezier curve, A = elliptical arc T = smooth quadratic bezier curveto. Z = closepath 176 Simple Vector Graphics (SVG) Beispiel 3 • Beleuchtete Kugel <?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG 20010904/DTD/svg10.dtd"> <svg width="100%" height="100%"> <defs> <radialGradient id="fade-to-black" cx="50%" cy="50%" r="50%" fx="50%" fy="50%" spreadMethod="pad" gradientUnits="objectBoundingBox"> <stop offset="0%" style="stop-color:rgb(255,255,255);stop-opacity:0"/> <stop offset="100%" style="stop-color:rgb(0,0,0);stop-opacity:1"/> </radialGradient> </defs> <ellipse cx="229.5" cy="200.5" rx="112.5" ry="100.5" style="fill:url(#fade-to-black)"/> 177 </svg> XSLT Auf SVG angewandt • XML Quelldokument <?xml version="1.0"?> <cubicles> <cubicle north="10" east="15" width="10" length="10"/> <cubicle north="0" east="0" width="10" length="10"/> </cubicles> 178 XSLT Auf SVG angewandt • XSL Transformation <?xml version='1.0'?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <svg xmlns="http://www.w3.org/2000/svg"> <title>Our Cubicles</title> <xsl:apply-templates select="cubicle"/> </svg> </xsl:template> <xsl:template match="cubicle"> <rect x="{north}" y="{east}" width="{width}" height="{length}"/> </xsl:template> </xsl:stylesheet> 179 XSLT Auf SVG angewandt • SVG Resultatdokument <?xml version="1.0" standalone="no"?> <svg xmlns="http://www.w3.org/2000/svg"> <title>Our Cubicles</title> <rect x="10" y="15" width="10" height="10"/> <rect x="0" y="0" width="10" height="10"/> </svg> 180 XSLT Strukturschema (1) XML Internalize / A DOM B A Skript xxxx yy zzz XSLT ZL Templates Function Calls A C API Impl XSLT Prozessor Strom ZL 181 XSLT Strukturschema (2) Internalize ZL Template ZL Template DOM Impl XML / A B A A C API Impl XSLT Prozessor Strom ZL 182 ASP Server Architektur (1) request Internet Server C C http .htm Active Server Page .asp ASP engine 183 ASP Server Architektur (2) Provider A Webservice f My Webservice .asp .htm f g Internet incl. state post back .net ASP engine class Provider B Webservice g 184 ASP Server Code • Inline Server Code <html> <body bgcolor="yellow"> <center> <h2>Hello W3Schools!</h2> <p><%Response.Write(now())%></p> </center> </body> </html> 185 ASP HTML Server Controls • <script runat="server"> Sub Page_Load link1.HRef="http://www.w3schools.com" End Sub </script> <html> Web Form <body> <form runat="server"> <a id="link1" runat="server">Visit W3Schools!</a> </form> HTML Server </body> Control </html> 186 ASP Web Server Controls • <asp:control_name id="some_id" runat="server"> • <html> <body> Calendar Control <form runat="server"> <asp:Calendar DayNameFormat="Full" runat="server"> <WeekendDayStyle BackColor="#fafad2" ForeColor="#ff0000" /> <DayHeaderStyle ForeColor="#0000ff" /> <TodayDayStyle BackColor="#00ff00" /> </asp:Calendar> </form> </body> </html> 187 ASP Web Server Controls • <html> XML Control <body> <form runat="server"> <asp:Xml DocumentSource="cdcatalog.xml" TransformSource="cdcatalog.xsl" runat="server" /> </form> <p><a href="cdcatalog.xml" target="_blank"> View XML file </a></p> <p><a href="cdcatalog.xsl" target="_blank"> View XSL file </a></p> </body> </html> 188 ASP Web Server Controls • <script runat="server"> Sub submit(Source As Object, e As EventArgs) button1.Text="You clicked me!" End Sub </script> <html> Web Server <body> Control <form runat="server"> <asp:Button id="button1" Text="Click me!" runat="server" OnClick="submit"/> </form> </body> </html> 189 ASP Validation Server Controls • <html> <body> <form runat="server"> Enter a number from 1 to 100: <asp:TextBox id="tbox1" runat="server" /> <br /><br /> <asp:Button Text="Submit" runat="server" /> <br /> <asp:RangeValidator ControlToValidate="tbox1" MinimumValue="1" MaximumValue="100" Type="Integer" EnableClientScript="false" Text="The value must be from 1 to 100!" runat="server" /> </form> Validation </body> Server Control 190 </html> ASP Event Handlers • <script runat="server">Sub Page_Load if Not Page.IsPostBack then lbl1.Text="The date and time is " & now() end if End Sub Sub submit(s As Object, e As EventArgs) lbl2.Text="Hello World!" End Sub </script> <html> <body> <form runat="server"> <h3><asp:label id="lbl1" runat="server" /></h3> <h3><asp:label id="lbl2" runat="server" /></h3> <asp:button text="Submit" onclick="submit" runat="server" /> </form> </body> </html> 191 ASP Volatile Content • <html> <body> <form action="demo_classicasp.aspx" method="post"> Your name: <input type="text" name="fname" size="20"> <input type="submit" value="Submit"> </form> <% dim fname fname=Request.Form("fname") If fname<>"" Then Response.Write("Hello " & fname & "!") End If %> </body> </html> 192 ASP Persistent Content • <script runat="server"> Sub submit(sender As Object, e As EventArgs) lbl1.Text="Hello " & txt1.Text & "!" End Sub </script> <html> <body> <form runat="server"> Your name: <asp:TextBox id="txt1" runat="server" /> <asp:Button OnClick="submit" Text="Submit" runat="server" /> <p> <asp:Label id="lbl1" runat="server" /></p> </form> </body> </html> 193 ASP Persistent Content • <form name="_ctl0" method="post" action="page.aspx" id="_ctl0"> <input type="hidden" name="__VIEWSTATE" value="dDwtNTI0ODU5MDE1Ozs+ ZBCF2ryjMpeVgUrY2eTj79HNl4Q=" /> .....some code </form> 194 ASP Data Binding via XML (1) • <%@ Import Namespace="System.Data" %> <script runat="server"> sub Page_Load if Not Page.IsPostBack then dim mycountries=New DataSet mycountries.ReadXml(MapPath("countries.xml")) rb.DataSource=mycountries rb.DataValueField="value" rb.DataTextField="text" rb.DataBind() end if end sub sub displayMessage(s as Object,e As EventArgs) lbl1.text="Your favorite country is: " & rb.SelectedItem.Text end sub 195 </script> ASP Data Binding via XML (2) • <html> <body> <form runat="server"> <asp:RadioButtonList id="rb" runat="server" AutoPostBack="True" onSelectedIndexChanged="displayMessage" /> <p> <asp:label id="lbl1" runat="server" /> </p> </form> </body> </html> 196 ASP Fallstudie Picture Market • Servicebeschreibung o o Kunde fordert Bild an Server liefert Zufallsbild • Servicebestandteile o Aktive Serverseite o „Businesslogic“ Modul o Kollektion von Bildern PictureMart.aspx Auf Serverseite PictureMart.mod pict1.gif, ..., pictN.gif 197 Fallstudie Picture Market PictureMart.aspx (1) suche in \bin Directory und Assemblycache <html> <head> <add assembly = "PictureMart.dll, Version=1.0"/> <script language="C#" runat="server"> public void Page_Load(Object sender, EventArgs E) { if (!(Page.IsPostBack) ) { Image1.ImageUrl = "pic/empty.gif"; } } void SubmitBtn_Click(Object sender, EventArgs e) { Image1.ImageUrl = PictureMart.PictureMart.Select(); } </script> </head> <body> 198 ... Fallstudie Picture Market PictureMart.aspx (2) ... </head> <body> <h3>Fun Picture Market</h3> Business Logic powered by Oberon for .net <form runat=server> <asp:Image ID = "Image1" ImageUrl = "pic/empty.gif" AlternateText = "empty" runat = "server"/> <p> <asp:button text = „Apply“ OnClick = "SubmitBtn_Click" runat = server/> </form> </body> </html> 199 Fallstudie Picture Market PictureMart.mod Oberon for .NET MODULE PictureMart; IMPORT System; VAR rand: System.Random; PROCEDURE Select* (): System.String; BEGIN RETURN System.String.Concat { (System.String, System.String, System.String): System.String } ("pic/pict", System.Convert.ToString(rand.Next(1, 14)), ".gif"); END Select; BEGIN NEW(rand) END PictureMart. 200