Tidigare TDDC74 Programming: Abstraktion och modellering Föreläsning 4 Symboler, Par, Listor Representation av par, Grafisk notation för par Representation av listor mha par Typiska listhanteringsprocedurer n Tidigare i kursen har vi skrivit procedurer som jobbar med tal. I princip materialet i kapitel 1 i kursboken n Detta för att kunna koncentrera oss på procedurer och processer de skapar Primitiv data: Tal, Symboler, Strängar,... Primitiv data av olika slag skapas genom att man skriver den enligt en särskild format n Tal: 2, 3.14 n Symboler: x, y, square, pi n Strängar: whatever, 123, \ n Tecken: #\2, #\c, #\C, #\$ n Boolsk: #t, #f Vilken typ av primitiv data har vi? Procedurer som testar: n Tal: number? n Symboler: symbol? n Strängar: string? n Tecken: char? n Boolskt: boolean? Jämföra primitiv data Symboler och QUOTE n Tal: =, <, > n Symboler: symbol=? n Strängar: string=?, string<?, string<=?, string>=? n Tecken: char=?, char<?, char>? n Boolskt: eqv? n Måste skilja mellan symboler som namn och symboler som data n QUOTE är en specialform som markerar att dess argument är data n Namn står för något annat symboler står för sig själva n Användning: (quote square) eller square
Symboler och QUOTE Sammansatt data (quote x) evalueras till symbolen x, men x evalueras till det värde som x är satt till. > (define namn 23) > (quote namn) namn > namn 23 n När data sammankopplas får vi sammansatt data Operationer av intresse - sammansatt data n Konstruktion n Selektion av delar Par n En grundläggande typ av sammansatt data i Scheme n Igenkänning och jämförelse n Förändring av delar (kapitel 3 SICP, fö 7-9) n Presentation eller utskrivning Par Grafisk notation för par n Konstruktion: proceduren CONS som tar två argument n Selektion: Procedurerna CAR och CDR används för att hämta car- resp. cdr-delen n Igenkänning: predikaren pair? används för att testa huruvida något är ett par n Presentation/utskrivning: ett par som skapats med (cons 1 2), skrivs ut som (1. 2) i Scheme
Grafisk notation för par (cons 10 20) Grafisk notation för par - alternativ (cons 10 20) 10 2 10 20 Grafisk notation för par (cons 10 (cons 20 30)) Grafisk notation för par - alternativ (cons 10 (cons 20 30)) 10 20 30 10 20 30 Grafisk notation för par Grafisk notation för par (define x (cons 10 (cons 20 30))) x 10 20 30 (define x (cons (cons 10 40) (cons 20 30))) x 10 40 20 30 Varje anrop till CONS skapar ett par
Listor i Scheme En lista i Scheme är antingen n en ordnad sekvens av element, eller n en tom lista utan några element Konstruktion av listor Konstruktion: tomma listan skapas med hjälp av (). Andra listor skapas med hjälp av en ordnad sekvens av par, där sista parets cdr-del är () Selektion: first och rest Igenkänning och jämförelse: list? Förändring av delar (kapitel 3 SICP, fö 7-9) Presentation eller utskrivning Konstruktion av listor Konstruktion: tomma listan skapas med hjälp av uttrycket () Andra listor skapas med hjälp av en ordnad sekvens av par, där car-delen av varje par innehåller ett element ur listan och cdr-delen innehåller resten av listan Sista parets cdr-del är () Exempel på listkonstruktion (cons 1 (cons 2 (cons 3 ()))) Skapar listan (1 2 3) proceduren LIST (list 1 2 3) är en förkortning för (cons 1 (cons 2 (cons 3 ()))) Ekvivalenta listor (cons e1 (cons e2 (cons (cons en ())))) (list e1 e2 en) (e1 e2 en)
Ekvivalenta listor Ej ekvivalenta listor (list 1 2 3 4) (1 2 3 4) (list e1 e2 en) (e1 e2 en) Listor i Racket I Racket skrivs listor ut så här: '(1 2 3) '(0 1 1 2 3) '(6 28) Samma element men olika strukturer Följande strukturer är olika: (list 'a 'b 'c) (cons 'a (cons b c)) Den första skapar en lista medan den andra skapar en godtyckligt consstruktur. Har vi en lista: null? eller list? null? testar om vi har en tom lista list? testar om vi har en lista (null? ()) är #t (list? ()) är #t (null? (list 1 2)) är #f (list? (list 1 2) är #t Jämför listor Använd eqv? för att testa huruvida två listor är samma Använd equal? för att testa huruvida två listor innehåller samma element
Grafisk notation för listor Grafisk notation för listor - generellt Tomma listan: () Lista med 1 element: (list 10) 10 () En lista som innehåller ett eller flera element representeras av en följd av CONS-celler enligt: 2 elements: (list 10 20) 10 20 () e1 e2... en () OBS! Listor kan innehålla listor (null? (list ())) är #f () () (list ()) är samma sak som (cons () ()) ((1 2) (a (b) c)) () 1 2 () a c () b () Listor kan innehålla listor ((1 2) (a (b) c)) () Toppnivån Dellistor CONS-celler kan pekas ut från olika håll (define pair (cons 1 2)) (define pairpair (cons pair pair)) pairpair 1 2 () a c () Del av en del b () pair 1 2
CONS-celler kan pekas ut från olika håll (define pair (cons 1 2)) (define pairpair (cons pair pair)) (define metoo pair) pairpair CONS-celler kan pekas ut från olika håll (define pair (cons 1 2)) (define pairpair (cons pair pair)) (define metoo pair) (define andme (cons pairpair metoo)) pairpair pair metoo andme pair metoo 1 2 1 2 Utskrivning i Racket OBS! Par (eller CONS-lådor) skrivs ut i punktnotationen: (cons 1 2) som (1. 2) (cons (cons 1 2) (cons 3 4)) som ((1. 2) 3. 4) (cons 1 (cons 2 ())) som (1 2) Punktnotationen förvånar oss ibland, men det är bara acceptera att det är så :) (cons (cons 1 2) (cons 3 4)) skrivs ut som ((1. 2) 3. 4) och inte som man eventuellt tror ((1. 2). (3. 4)) Listor - Utskrivning i Racket Listor skrivs ut av Racket enligt följande exempel: () (1 2 3) (0 1 1 2 3) (6 (28 (486))) Sekvenser och Listor Med lista och sekvens menar vi ofta samma sak, men vi väljer att skilja på dem något i fall tvetydlighet uppstår När alla elementen i en lista betraktas och behandlas på samma sätt säger vi att vi jobbar med en sekvens. När vissa element i listan är dellistor och skall behandlas på annat sätt än element som inte är dellistor då föredrar vi att inte kalla denna lista för en sekvens utan en lista
Exempel på listhanteringsprogram Beräkna längden av en sekvens Sätt ihop två sekvenser Vänd på en sekvens Ersätt förekomster av ett element med ett annat i en sekvens eller lista Programmönster: #1 jobba med sekvenser Två fall: Sekvensen är tom: () Sekvensen ej tom: (a b c) Programmönster: #1 (DEFINE (FN SEQ) (IF (NULL? SEQ) <null-result> (<operation> (FN (REST SEQ))))) Programmönster: #1 (DEFINE (FN SEQ) (IF (NULL? SEQ) <null-result> (<operation> (FN (CDR SEQ))))) (define (square-all seq) (if (null? seq) () (cons (square (first seq)) (square-all (rest seq))))) (define (satt-ihop seq-1 seq-2) (if (null? seq-1) seq-2 (cons (first seq-1) (satt-ihop (rest seq-1) seq-2)))) Programmönster: #1i Iterativt hantering av sekvenser (DEFINE (FN SEQ) (DEFINE (ITER SEQ RESULT) (IF (NULL? SEQ) RESULT (ITER (CDR SEQ) (accum RESULT)))) (ITER SEQ <null-result>)) (define (sum-seq seq) (define (iter seq result) (if (null? seq) result (iter (rest seq) (+ result (first seq))))) (iter seq 0)) Programmönster: #2 jobba med sekvenser Tre fall: Sekvensen är tom: () Sekvensen börjar med ett element som uppfyller ett villkor: (2 a b) Sekvensen börjar med ett element som inte uppfyller ett villkor: (a 2 c) Det kan bli flera fall i fall vi har flera olika villkor, men fortfarande samma struktur i
Programmönster: #2 Listor som sekvenser Exempel: ingår e i seq? (DEFINE (FN SEQ) (COND ((NULL? SEQ) <null-result>) (<condition> <result>) (ELSE (<operation> (FN (CDR SEQ)))))) (define (element? e seq) (cond ((null? Seq) #f) ((eqv? e (car seq)) #t) (else (element? e (cdr seq))))) Programmönster: #2 Listor som sekvenser. Ersätt förekomster av OLD med NEW i en lista (define (replace seq old new) (cond ((null? seq) ()) ((eq? (first seq) old) (cons new (replace (rest seq) old new))) (else (cons (first seq) (replace (rest seq) old new)))))) Programmönster: #2 Listor som sekvenser. Denna lösning är i princip samma som förra (define (replace seq old new) (if (null? seq) () (cons (if (eq? (first seq) old) new (first seq)) (replace (rest seq) old new)))) Programmönster: #2 Listor som sekvenser. (define (get-position el seq) (define (helper seq k) (cond ((null? seq) -1) ((eq? el (car seq)) k) (else (helper (cdr seq) (+ k 1))))) (helper seq 0)) Programmönster: #2 Listor som sekvenser. (define (merge seq1 seq2) (cond ((null? seq1) seq2) ((null? seq2) seq1) ((< (first seq1) (first seq2)) (cons (first seq1) (merge (rest seq1) seq2))) (else (cons (first seq2) (merge (rest seq1) seq2))))) Programmönster: #3 listor där elementen är listor Vanligtvis har vi 3 fall: Tom lista: () Första elementet ej lista: (a (b c) (d)) Generella fallet: ((a b) (b c) (d))
#3 exempel: summan av tal i lista med dellistor (define (sum lol) (cond ((null? lol) 0) ((number? (first lol)) (+ (first lol) (sum (rest lol)))) (else (+ (sum (first lol)) (sum (rest lol))))))