Repetition Introduktion Repetition i Exemplen fac Orginalet I Scheme använde vi rekursion för all slags repetition. Efterom Scheme är ett funktionellt språk återsänder alla språkkonstruktioner ett värde men i (mellan-)lagras värden i variabler. Man kan alltså ha styrstrukturer som inte kräver rekursion för repetitiva beräkningar. har flera sådana och jag kommer ge exempel på hur de används. Jag använder två olika exempel som vi redan studerat både i Scheme och (define fac (if (= n 0) 1 (* n (fac (- n 1)))))) Svansrekursiv (define fac (define fac-svans (lambda (m res) (if (> m n) res (fac-svans (+ m 1) (* res m))))) (fac-svans 2 1))) DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 1 / 20 DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 2 / 20 Exemplen fac i Exemplen fac motivering Direktkopia av den svansrekursiva Scheme-varianten FUNCTION facsvans(m, res: Integer): Integer; IF m > n THEN facsvans := res ELSE facsvans := facsvans(m + 1, res * m) fac := facsvans(2, 1) Betraktar man en trace på fac-svans eller gör en utskrift från motsvarande -program får man m res 2 1 3 2 4 6 5 24 6 120 Vi ser att resultatet erhålls genom att parametrarna m och res uppdateras för varje anrop och att det som lagrats i parametern res lämnas som resultat då m passerat värdet för n. Det räcker alltså att sätta initalvärden på res och m och uppdatera dem utan extra anrop. I kan man formulera detta direkt utan rekursion. DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 3 / 20 DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 4 / 20
Repetition i while Repetition i while formellt FUNCTION fac(n : Integer) : Integer; VAR m, res : Integer; { variabler för mellanlagring} { ersätter inre funk.param.} m := 2; res := 1; { initialvärden } WHILE m <= n DO { villkoret inverterat } res := res * m; { uppdatera res } { uppdatera m } { slut på slingan } { återsänd resultatet } while (villkors-) uttryck I funktionen fac är satsen en sammansatt sats eftersom jag vill utföra mer än en sak. I WHILE-satsen kollar man om villkoret är uppfyllt innan man gör något. Skulle villkoret inte vara uppfyllt då programmet stöter på WHILE-satsen så utförs ingenting Man måste, som vid rekursion, vara noga med att se till att man kommer till en situation där villkoret inte längre är uppfyllt. Man har ingen kompilatoranalys till hjälp. Man kan tänka sig att man först vill göra något och sedan kolla om man ska göra om. stöder även detta. do sats DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 5 / 20 DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 6 / 20 Repetition i repeat... until Repetition i repeat... until formellt VAR m, res : Integer; m := 1; res := 1; REPEAT res := res * m; UNTIL m > n; repeat sats until ; (villkors-) uttryck Man kan utan sammansatt sats sätta in flera satser mellan REPEAT och UNTIL Man utför alla satser minst en gång Man måste även här vara noga med att slutvillkoret kommer att uppfyllas Eftersom vi vet både start och slutvillkor och dessa är taljämförelser så kan vi ju faktiskt avgöra exakt hur många gånger vi ska utföra modifikationen av variablerna. Det kan vi utnyttja på två sätt: DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 7 / 20 DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 8 / 20
Repetition i for... to/downto Repetition i for... to/downto formellt VAR m, res : Integer; res := 1; FOR m := 2 TO n DO res := res * m; for (variabel-) identifierare := uttryck to downto VAR res : Integer; res := 1; FOR n := n DOWNTO 2 DO res := res * n; uttryck do sats Mindre formellt (och lättare att resonera kring): FOR variabel := startvärde TO / DOWNTO slutvärde DO sats DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 9 / 20 DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 10 / 20 Repetition i for... to/downto formellt Rekursion kontra iteration för- och nackdelar FOR variabel := startvärde TO / DOWNTO slutvärde DO sats I FOR...TO-satsen kontrolleras att startvärdet är mindre än eller lika med slutvärdet, annars utförs ingenting Självklart tvärtom i FOR...DOWNTO-satsen Satsen utförs för varje värde, inklusive start- och slutvärdena Start och slutvärdena ska vara av samma (diskreta typ) Steget är alltid i någon mening 1 Repetition med de nu visade konstruktionerna kallas iteration Vid rekursion behöver man bara tänka på Hur vet man att man är klar? Vad gör man då? Hur tar man ett steg närmare lösningen? Vid iteration måste man tänka på allt samtidigt men Iteration är resurssnålt För att rekursion ska vara resurssnålt måste man använda ett språk som kan eliminera svansrekursion (som Scheme, ML, Haskell eller Miranda) skriva svansrekursiva program (inte alltid enkelt) Vi har nu tre olika loopkonstruktioner: 1. REPEAT... UNTIL villkor; 2. WHILE villkor DO sats; 3. FOR styrvariabel := start TO slut DO s; FOR styrvariabel := start DOWNTO slut DO s; DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 11 / 20 DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 12 / 20
Iteration exempel 2 (fib) i Scheme Iteration exempel 2 (fib) i Scheme... Rekursivt i Scheme: (define fib (if (< n 2) 1 (+ (fib (- n 1)) (fib (- n 2)))))) Svansrekursivt (define fib (define fib-inner (lambda (m f1 f2) (if (> m n) f2 (fib-inner (+ m 1) f2 (+ f1 f2))))) (fib-inner 1 0 1))) Trace av svansrekursiva varianten > (fib 5) (fib-inner 1 0 1) (fib-inner 2 1 1) (fib-inner 3 1 2) (fib-inner 4 2 3) (fib-inner 5 3 5) (fib-inner 6 5 8) 8 8 DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 13 / 20 DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 14 / 20 Iteration exempel 2 (fib) i Iteration exempel 2 (fib) med WHILE FUNCTION inner(m, f1, f2 : Integer) : Integer; IF m > n THEN inner := f2 ELSE inner := inner(m + 1, f2, f1 + f2) fib := inner(1, 0, 1) VAR m, f1, f2, tmp : Integer; m := 1; f1 := 0; f2 := 1; WHILE m <= n DO DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 15 / 20 DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 16 / 20
Iteration exempel 2 (fib) med REPEAT Iteration exempel 2 (fib) med FOR...TO fib := inner(1, 0, 1) m := 1; f1 := 0; f2 := 1; REPEAT UNTIL m > n; VAR m, f1, f2, tmp : Integer; f1 := 0; f2 := 1; FOR m := 1 TO n DO DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 17 / 20 DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 18 / 20 Iteration exempel 2 (fib) med FOR...DOWNTO Iteration exempel 3: iterate i newton-programmet VAR f1, f2, tmp : Integer; f1 := 0; f2 := 1; FOR n := n DOWNTO 1 DO FUNCTION iter(x, eps: Real; FUNCTION next(x:real; FUNCTION f(x:real):real):real; FUNCTION f(x: Real):Real): Real; WHILE abs(x-next(x, f)) >= eps DO x := next(x, f); iter := x DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 19 / 20 DA2001 (Föreläsning 12) Datalogi 1 Hösten 2010 20 / 20