Modularitet och tillstånd Stora system kräver en uppdelning. En lösning: modularitet Basera programmets struktur på den fysiska systemets struktur: En fysisk objekt en beräkningsobjekt Ett agerande en symbolisk operation På detta sätt, om vi utvidgar systemet så (förhoppningsvis) behöver vi bara addera nya objekt och operationer, utan att påverka den existerande lösning. Två strategier: Tillstånd Många objekt kan karakteriseras mha tillstånd ett bankkonto en bil en dator DrSchemes interpretator... koncentrera på objekt koncentrera på strömmar (informationsflöde) Jacek Malec, Dept. of Computer Science, Lund University 3 Jacek Malec, Dept. of Computer Science, Lund University 4 Lokalt tillstånd Ett exempel: ett bakkonto, med 1000:- SEK (dra-ut 250) 750 (dra-ut 250) 500 (dra-ut 600) "För lite på kontot" (dra-ut 150) 350 Implementation (define balance 100) (define (withdraw amount) "För lite på kontot")) Något nytt: set! en speciell form Något till: begin också en speciell form
Att skapa liknande objekt (define new-withdraw (let ((balance 100)) "För lite på kontot")))) Nu är balance osynlig, förutom för new-withdraw! balance är enkapslad (encapsulated) i proceduren new-withdraw. (define (make-withdraw "För lite på kontot"))) Hur det fungerar? (define W1 (make-withdraw 100)) (define W2 (make-withdraw 100)) (W1 50) (W2 70) (W2 40) (W1 40) Jacek Malec, Dept. of Computer Science, Lund University 7 Jacek Malec, Dept. of Computer Science, Lund University 8 Exempel, forts. (define (make-account (define (withdraw amount) "För lite på kontot")) (define (deposit amount) (set! balance (+ balance amount)) (define (dispatch m) (cond ((eq? m withdraw) withdraw) ((eq? m deposit) deposit) (else (error "Unknown request -- MAKE-ACCOUNT" m)))) dispatch) Exempel, forts. (define acc (make-account 100)) ((acc withdraw) 50) ((acc withdraw) 60) ((acc deposit) 40) ((acc withdraw) 60) (define acc2 (make-account 100)) Message passing!
Syntaktisk socker ((acc deposit) 40) (define (deposit accout amount) ((account deposit) amount)) (define (withdraw accout amount) ((account withdraw) amount)) (deposit acc 40) (withdraw acc 50) (define (transact account op-type amount) ((account op-type) amount)) (transact acc deposit 40) (transact acc withdraw 40) En nyttig abstraktionsbarriär! Nytta av tilldelning Ett exempel: slumptalsgenerator Vad är slumptal? (rand-update)= x (rand-update)= y (rand-update)= z x, y, z,... har de nödvändiga statistiska egenskaper Ett förslag: (define random-init 7) (define rand (let ((x random-init)) (lambda () (set! x (rand-update x)) x))) Jacek Malec, Dept. of Computer Science, Lund University 11 Jacek Malec, Dept. of Computer Science, Lund University 12 Exempel: Monte Carlo 6/π 2 är sannolikheten att två slumpmässiga heltal har inga gemensamma delare. Låt oss experimentera för att hitta π: (define (estimate-pi trials) (sqrt (/ 6 (monte-carlo trials cesaro-test)))) (define (cesaro-test) (= (gcd (rand) (rand)) 1)) (define (monte-carlo trials experiment) (define (iter trials-remaining trials-passed) (cond ((= trials-remaining 0) (/ trials-passed trials)) ((experiment) (+ trials-passed 1))) (else trials-passed)))) (iter trials 0))
Utan tilldelning: (define (estimate-pi trials) (sqrt (/ 6 (random-gcd-test trials random-init)))) (define (random-gcd-test trials initial-x) (define (iter trials-remaining trials-passed x) (let ((x1 (rand-update x))) (let ((x2 (rand-update x1))) (cond ((= trials-remaining 0) (/ trials-passed trials)) ((= (gcd x1 x2) 1) (+ trials-passed 1) x2)) (else trials-passed x2)))))) (iter trials 0 initial-x)) Tilldelningen kostar! (define (make-simplified-withdraw (set! balance ) (define W (make-simplified-withdraw 25)) (W 20) (W 10) Jamför det med: (define (make-decrementer ) (define D (make-decrementer 25)) (D 20) (D 10) Inget tillstånd hos D! Jacek Malec, Dept. of Computer Science, Lund University 15 Jacek Malec, Dept. of Computer Science, Lund University 16 Substitutionsmodellen ((make-decrementer 25) 20) Substitutionsmodellen: symboler är namn på värde! ( (- 25 amount)) 20) (- 25 20) Låt oss prova på make-simplified-withdraw: ((make-simplified-withdraw 25) 20) ( (set! balance (- 25 amount)) 25) 20) (set! balance (- 25 20)) 25 Fel! Det finns två balance: innan set! och efter set! Tilldelning: en variabel är inte längre ett namn,utanenbehållare, en plats för ett värde Konsekvens: två saker som ser lika ut behöver inte vara (exakt) lika. Vad betyder en och samma sak? (define D1 (make-decrementer 25)) (define D2 (make-decrementer 25)) (define W1 (make-simplified-withdraw 25)) (define W2 (make-simplified-withdraw 25)) Är D1 och D2 en och samma sak? Är W1 och W2 en och samma sak?
Ett exempel till: (define peter-acc (make-account 100)) (define paul-acc (make-account 100)) (define peter-acc (make-account 100)) (define paul-acc peter-acc) Är peter-acc och paul-acc en och samma sak? Ja i det andra fallet. Men hur vet vi det? Endast genom att analysera programkoden! Om imperativ programmering (define (factorial n) (define (iter product counter) (if (> counter n) product (iter (* counter product) (+ counter 1)))) (iter 1 1)) Jacek Malec, Dept. of Computer Science, Lund University 19 Även klarare: (define (factorial n) (let ((product 1) (counter 1)) (define (iter) (if (> counter n) product (begin (set! product (* counter product)) (set! counter (+ counter 1)) (iter)))) (iter))) Hur vet vi att ordningen på (set! product (* counter product)) (set! counter (+ counter 1)) är rätt? Jobbigt att analysera. I funktionell programmering problemet finns ej!