Abstraktion Inom programmeringstekniken används två former av abstraktion dataabstraktion och programabstraktion. Dataabstraktion handlar om aggregat för att gruppera samhörande data. Programabstraktion sönderfaller i två delar procedur- resp funktions-abstraktion. funktionsabstraktion procedurabstraktion DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 1 / 27
Abstraktion... En procedurabstraktion har som uppgift att uppdatera för proceduren globala storheter/strukturer. En funktionsabstraktion utför en beräkning och återsänder ett (eventuellt komplext) värde. Alla funktionsabstraktioner återsänder ett värde till anropspunkten. Detta kan ske genom att, som i funktionella språk, det sist beräknade värdet återsänds eller, som i vissa imperativa språk, man dels talar om att beräkningen inte kan fortsätta, dels anger ett värde att återsända eller, som i andra imperativa språk, funktionen har en pseudovariabel (funktionens namn) vilken tilldelas ett värde. DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 2 / 27
Abstraktion... Ex: en funktion som ger minsta värdet av tre: Pascal: FUNCTION min(a, b, c: Integer): Integer; VAR tmpmin: Integer; BEGIN tmpmin := a; IF b < tmpmin THEN tmpmin := b; IF c < tmpmin THEN tmpmin := c; min := tmpmin; END; DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 3 / 27
Abstraktion... Scheme: (define (min a b c) (if (and (< a b) (< a c)) a (if (< b c) b c))) DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 4 / 27
Abstraktion... C: min (a, b, c) int a, b, c; { if (a < b && a < c) { return a; } else if (b < c) { return b; } else { return c; } } DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 5 / 27
Abstraktion... Men funktioner i Scheme kan återsända sammansatta värden: (define (minmax x) (define (inner x min max) (cond ((null? x) (list min max)) ((< (car x) min) (inner (cdr x) (car x) max)) ((> (car x) max) (inner (cdr x) min (car x))) (else (inner (cdr x) min max)))) (inner (cdr x) (car x) (car x))) DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 6 / 27
Abstraktion... Så vissa procedurer i t ex Pascal måste betraktas som funktionsabstraktioner: PROCEDURE minmax(v: vector; VAR min, max: Integer); VAR i: index; BEGIN min := v[1]; max := v[1]; FOR i := 2 TO maxindex DO IF v[i] < min THEN min := v[i] ELSE IF v[i] > max THEN max := v[i]; END; DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 7 / 27
Abstraktion... Procedurabstraktioner är abstraktioner som endast arbetar via bieffekter, t.ex. skiver till fil, uppdaterar globala variabler... I funktionella språk åstadkoms procedurabstraktioner genom att vissa funktioner får returnera ett resultat som man inte tar hand om eftersom resultatet är irrelevant för funktionen och ingen är intresserad av det. Ex: Scheme: (define (errormsg msg) (display msg) (newline)) DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 8 / 27
Abstraktion... Pascal: PROCEDURE printstars(n: Integer); BEGIN FOR i := 1 TO n DO Write( * ); WriteLn; END; DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 9 / 27
Abstraktion... En abstraktion skall vara väldefinierad Abstraktionen skall utföra endast en (ev komplex) arbetsuppgift, och utföra denna enda uppgift väl (= korrekt och effektivt). modulärt begriplig Abstraktionen skall ha en betydelse även ryckt ur sitt sammanhan, dvs inte arbeta med globala storheter (skicka allt med parametrarna). robust Abstraktionen upptäcker när indata ligger utanför definitionsområdet och hanterar felsituationer på ett relevant sätt. väldokumenterad Abstraktionen skall vara försedd med pre- och postvillkor och om delar av algoritmen är svårbegriplig skall denna del vara kommenterad DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 10 / 27
Abstraktion... I vissa språk kan vi göra högre ordningens abstraktioner: Funktioner och procedurer som tar funktioner och procedurer som parametrar PROCEDURE dotoeach(alist: listptr; PROCEDURE todo(var e: elementptr)); VAR tmp: elementptr; BEGIN tmp := alist^.first; WHILE tmp <> NIL DO BEGIN todo(tmp); tmp := tmp^.next END END; (define (do-to-each alist f) (if (null? alist) () (cons (f (car alist)) (do-to-each (cdr alist) f)))) DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 11 / 27
Abstraktion... Funktioner som ger funktioner som resultat (define (power n) (lambda (x) (expt x n))) ML med: fun upcasechar (s: string) = if ord s >= ord "a" andalso ord s <= ord "z" then chr (ord s + ord "A" - ord "a") else s; kan upcase skrivas som: val upcase = implode o map (upcasechar) o explode; DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 12 / 27
Parametrar För att en abstraktion skall vara modulärt begriplig måste alla strukturer och storheter som används av abstraktionen sändas som parametrar. Det är då viktigt att parametrarna sänds med rätt mekanism. Olika språk ger då olika möjligheter, beroende på vad som kan sändas och vilka mekanismer man kan använda. Traditionellt skiljer man på tre olika mekanismer DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 13 / 27
Värdeöverföring Grundläggande mekanism i de flesta programspråken. Den aktuella parametern evalueras och det erhållna värdet substitueras in för varje förekomst av den formella parametern i algoritmen. FUNCTION f(x, y: Integer): Integer; BEGIN x := x + y; f := 2 * x END; DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 14 / 27
Referensöverföring I Pascal sker referensöverföring om parametern föregås av VAR eller om parametern är en funktion eller procedur. Det innebär att den formella parameter är en referens till den aktuella parametern. En referens kan ses som en adress till den aktuella variabeln, proceduren eller funktionen. PROCEDURE minmax(v: vector; VAR min, max: Integer); VAR i: index; BEGIN min := v[1]; max := v[1]; FOR i := 2 TO maxindex DO IF v[i] < min THEN min := v[i] ELSE IF v[i] > max THEN max := v[i]; END; DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 15 / 27
Namnöverföring Den aktuella parametern evalueras inte förrän den förekommer i algoritmen, d v s att den aktuella parametern, utan evaluering, substitueras för varje förekomst av den formella parametern. Ex (Simula): REAL PROCEDURE sum(x, i, m, n); NAME x, i; REAL x; INTEGER i, m, n; BEGIN REAL summa; summa := 0; FOR i := m STEP 1 UNTIL n DO summa := summa + x; sum := summa END; anropet OutFix(sum(a(i) * b(i), i, 1, 100), 10, 5); ger a(1) * b(1) + a(2) * b(2) +... + a(100) * b(100) Detta brukar även kallas lat evaluering, d v s inga parametrar evalueras förrän de behövs för beräkningen. Exemplet är också en bra illustration av att bieffekter ger obegripliga resultat ibland. DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 16 / 27
Parametrar... Intimt förknippat med de olika parameteröverföringsmekanismerna är beräkningsordning vid utförande av abstraktioners algoritmer. Med applikativ ordning beräknas alltid parametrars värden innan anropet till abstraktionen utförs. Med lat evaluering eller normal ordning erhålls en annan beräkningsordning, men där alla parametrar behandlas lika. Det går inte att evaluera procedur-/funktions-parametrar förrän då de förekommer i algoritmen vilka argument skulle man använda? Alltså låter man alla parametrar hanteras lika med sen eller lat evalueringsordning. Två språk av de jag känner till har lat evaluering Miranda (liknar ML) och Haskell, Två ger valmöjlighet Simula och Algol60 De flesta har applikativ ordning, men gör undantag för abstraktioner. DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 17 / 27
Inkapsling, abstrakta datatyper Med växande program växer kravet på återanvänbarhet för programkod, kravet på att delprogram skall fungera i alla möjliga sammanhang och därmed kraven på modulär begriplighet, möjlighet att gömma modulers inre struktur, och minimala lättbegripliga kommunikationsgränssnitt mellan moduler. Antalet programmerare kan vara stort vid framtagandet av stora program. Därför är det viktigt med effektivitet (återanvända andras kod, generella, lätt anpassbara, lättbegripliga moduler). Det enda programmeraren skall behöva veta är vad modulen gör. Ansvaret för att modulen gör rätt ligger hos implementatören. DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 18 / 27
Moduler Modularisering sker genom abstraktion. De moduler vi hittills diskuterat är funktioner och procedurer. För att funktioner och procedurer skall passa som moduler gäller utöver modulär begriplighet att de skall vara minimala, dvs att varje procedur/funktion utför endast en väl avgränsad uppgift och att modulen har ingångar endast för det som verkligen behövs för uppgiften och att resultatet är enbart det eftersökta. Man skiljer också mellan procedurer vars uppgift utförs genom bieffekter och funktioner vars utförande ger ett resultat som levereras till omgivningen antingen genom ett funktionsvärde eller genom parametrar om det aktuella språket inte tillåter funktioner att leverera komplexa resultat. Generellt sett skall värden levereras antingen genom funktionsvärde eller via parametrar. Aldrig genom en kombination av dessa. DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 19 / 27
Moduler... Om funktioner i det aktuella språket kan leverera komplexa värden skall endast funktioner användas då ett i datorn representerbart resultat förväntas. Standard Pascal och Scheme har inget modulbegrepp (utöver funktions- och procedurabstraktioner). I Scheme kan man läsa in filer med definitioner när som helst i ett program. I Pascal är en vanlig utvidgning s.k. Units. Dessa är filer som delas in i två delar av de reserverade orden INTERFACE och IMPLEMENTATION. Allt som definieras i gränssnittsdelen- oftast funktions- och procedurhuvuden - syns i det anropande programmet, men det som finns i implementationsdelen - hjälpfunktioner/procedurer/datastrukturer och funktions- /procedurkroppar - syns inte. DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 20 / 27
Moduler... Detta är inspirerat av modernare språks modulfaciliteter. I vissa fall kan konceptuellt sammanhörande datastrukturer, funktioner och procedurer föras samman i en modul så att det program som öppnar modulen får tillgång till alla datastrukturer/funktioner/ procedurer i paketet. Även här gäller regeln om minimalitet. Modulen skall då hantera ett koncept, t.ex. trigonometriska funktioner eller vektorer i rymden. DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 21 / 27
Moduler... (define (three-d-vector x y z) (define (scale s) (three-d-vector (* s x) (* s y) (* s z))) (define (add v) (three-d-vector (+ x (v get-x)) (+ y (v get-y)) (+ z (v get-z)))) (define (sub v) (three-d-vector (- x (v get-x)) (- y (v get-y)) (- z (v get-z)))) (define (length) (sqrt (+ (* x x) (* y y) (* z z)))) (define (dotproduct v) (+ (* x (v get-x)) (* y (v get-y)) (* z (v get-z)))) (define (vectorproduct v) (three-d-vector (- (* y (v get-z)) (* z (v get-y))) (- (* z (v get-x)) (* x (v get-z))) (- (* x (v get-y)) (* y (v get-x))))) DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 22 / 27
Moduler... (lambda (m. n) (cond ((eq? m get-x) x) ((eq? m get-y) y) ((eq? m get-z) z) ((eq? m add) (add (car n))) ((eq? m sub) (sub (car n))) ((eq? m length) (length)) ((eq? m dotproduct) (dotproduct (car n))) ((eq? m vectorproduct) (vectorproduct (car n)))))) DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 23 / 27
Moduler... Betraktar man exemplet med vektorer i rymden kan man konstatera att operationerna är grundläggande för typen vector och man kan betrakta typen vector som bestående av alla element som kan tillverkas med hjälp av tripler av reella tal. Typen tillsammans med en eller flera konstruktorer och de grundläggande operationerna kan bilda en abstrakt datatyp. Även för abstrakta datatyper gäller minimalitet: Datastrukturen skall endast innehålla exakt det som krävs. Operationsmängden skall också innehålla endast det som hör samman med typen, och helst bara de grundläggande konstruktorerna, selektorerna och operationer. DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 24 / 27
Moduler... Om man behöver hjälpstrukturer/funktioner skall dessa helst döljas för omgivningen så att man inte frestas använda dem direkt. Sådan användning av hjälpstrukturer/funktioner och objektens inre struktur kan ha svåröverskådliga följder. DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 25 / 27
Moduler... flyttfunktion namnfunktion zoomfunktion wind stängfunktion scrollfunktion scrollfunktion sizefunktion DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 26 / 27
Moduler... Båda typerna av modul som nu diskuterats finns i flera andra språk, ADA, Simula (vassare), SmallTalk (abstyp, men vassare), C++ (vassare), Eiffel (vassare), Java (vassare) m.m. I vissa språk finns det endast i utvidgningar av olika slag. Bland de vassaste Pascalvarianterna är Borland (Turbo) Pascal. Det nya mode-språket Java har vad man kallar "interface"(gränssnitt), en sorts signaturer (en slags minsta gemensam nämnare, alla måste uppfylla minst de stipulerade kraven). En modul som implementerat ett gränssnitt tvingas att tillhandahålla åtminstone den i gränssnittet stipulerade funktionalteten. Viktigast är abstraktion och gömmande av detaljer. Man gömmer detaljer för att slippa veta mer än hur man använder modulen och för att undvika fatala misstag. DA2001 (Föreläsning 26) Datalogi 1 Hösten 2010 27 / 27