Föreläsning 3 Våra enkla funktioner eller procedurer Programmönster 1. Repetition 2. Högre-ordningens procedurer/programmönster - Procedurer som argument - Procedurer som returnerade värden 3. Scope och syntaktiska sockret LET kan vara resultatet av översättning av en fakta eller formel fallanalys och problem nedbrytning (t ex genom rekursion) generalisering av en existerande funktion/procedur specificering av en generell funktion/procedur (define (sum-squares a b) (+ (square a) (sum-squares (+ a 1) b)))) (define (sum-cubes a b) (+ (cube a) (sum-cubes (+ a 1) b)))) 1 2 3 Observera likheter: Bortsett från namnen, mycket lite skiljer dessa åt Det som skiljer dessa nu är den funktion de applicerar till a Helt rika, förutsatt att fn specificeras på något sätt (define (sum-squares a b) (+ (square a) (sum-squares (+ a 1) b)))) (define (sum-cubes a b) (+ (cube a) (sum-cubes (+ a 1) b)))) (+ (square a) (+ (cube a) 4 5 6
Generalisering genom paramtrisering Sigma är nu en generell funktion Man kan tänka sig olika varianter på Sigma (sigma (+ a 2) b fn)))) 7 8 9 Ytterligare parametriseing och därmed generalisering av Sigma Använd generell sigma Ackumulation genom summering och multiplicering (define (sum-squares a b) (sigma a b square inc)) (define (sum-cubes a b) (sigma a b cube inc)) Liten uppgift: Hur skriva ett program som summerar en följd av heltal? (define (mult a b fn next) (mult (next a) b fn next)))) 10 11 12
Annan typ av ackumulation Låt oss tillfälligt kalla båda för acc Mycket lite som skiljer de åt (define (mult a b fn next) (mult (next a) b fn next)))) 13 14 15 Ytterligare parametrisering av dessa ackumulationer Ytterligare parametrisering av dessa ackumulationer Ytterligare generalisering eller parametrisering av ackumulationer 16 17 18
En mycket generell ackumulation Fixa parametrarna till en generell ackumulation för att få en mer speci. ackumulation Fixa parametrarna till en generell ackumulation för att få en mer speci. ackumulation (acc a b fn next 0 +)) (define (sum a b) (acc a b (lambda (x) x) inc 0 +)) 19 20 21 Definera specifika ackumulationer i termer av acc Programmera genom att använda programmönster Procedurer som returnerade värden (define (sum a b) (acc a b (lambda (x) x) inc 0 +)) Så ett sätt att skapa program är att skicka olika parametrar till generella program och på det sättet skapa de program som utför specifika jobb. I Scheme är detta möjligt eftersom man kan ha så kallade högre-ordningens procedurer. Exempel: Sammansättning av två funktioner f(g(x)) (define compose (lambda (f g) (lambda (x) (f (g x))))) (define (compose f g) (lambda (x) (f (g x)))) 22 23 24
Användning av procedurer som returneras som värde exempel: double repeatfn (define compose (lambda (f g) (lambda (x) (f (g x))))) ((compose inc sqr) 3) Uppgift: Använd substitutionsmodellen för att visa hur detta uttryck evalueras. Skriv en funktion double som tar en funktion f med en parameter och som returnerar en annan funktion g (också med en parameter). g(x) skall motsvara f(f(x)). Skriv en funktion repeatfn med två parametrar f och n, där f är en funktion med en parameter och n är ett heltal 1. repeatfn skall returnera en funktion som applicerar f, n gånger. dvs, f(f(f f(x))). repeatfn(f, n) = f om n=1 λ(x) repeatfn(f, n-1)) f(x) 25 26 27 Scope Exempel Scope: lokal vs global Ett namn i Scheme som betecknar ett värde eller en procedur har en Scope Vidd eller sammanhang är förmodligen bra svenska ord för detta begrepp, men vi fortsätter att använda Scope Scope definierar i vilken del av programkoden ett givet namn gäller (define add1 (+ number 10))) Scopen för number är procedurens kropp. >(add10 3) 13 > number Error: reference to undefined identifier: number (define number 20) (define add1 (+ number 10))) > (add10 15) 25 > (add10 number) 30 28 29 30
Scope: lokal vs global Shadowing (skuggning) Exempel (define number 20) (define add1 (+ number 10))) > (add10 15) 25 > (add10 number) 30 (define number 23) (define add1 (+ number 10))) add10:s definition, genom att skapa ett namn, number, skuggar (eller med andra ord kör) över det globala värdet av number Skriv ett program som tar två heltal n och m och returnerar fib(n) om fib(n) = 2.fib(m) annars returnerar den fib(m). (define f (lambda (n m) (if (= (fib n) (* 2 (fib m))) (fib n) (fib m)))) OBS! Antingen (fib n) eller (fib m) beräknas två gånger. Onödigt! 31 32 33 Exempel: undvik onödiga beräkningar Exempel: LET snyggar upp koden LET Skriv ett program som tar två heltal n och m och returnerar fib(n) om fib(n) = 2.fib(m) annars returnerar den fib(m). (define f (lambda (n m) ((lambda (fibn fibm) (if (= fibn (* 2 fibm)) fibn fibm)) (fib n) (fib m)))) Skriv ett program som tar två heltal n och m och returnerar fib(n) om fib(n) = 2.fib(m) annars returnerar den fib(m). (define f (lambda (n m) (let ((fibn (fib n)) (fibm (fib m))) (if (= fibn (* 2 fibm)) fibn fibm)))) let används för att skapa lokala scope i vilket man evaluerar viss kod. (let ((<para 1 > <exp 1 >) (<para 2 > <exp 2 >) (<para n > <exp n >)) <body>) Lättare att följa än lambda 34 35 36
LET binder sina variabler parallellt, dvs vid samma ögonblick Fel Sammanfattning Testa följande: (define a 12) (let ((a 5) (b a)) (+ a b)) Syntaktiska fel Uttryck som ej går att evaluera Semantiska fel Syntaktisk korrekta men meningslösa uttryck Algoritmiska fel Programmet löser annat problem än det man vill Evaluering mha substitutionsmodellen Procedurer och processer Recursivt skrivna procedurer Rekursiva processer Iterativa processer Trädrekursiva processer Scope: lokala och globala namn let Högre ordningens procedurer Funktioner som argument Funktioner som värden 37 38 39