Kodningsstil

Av Thomas Padron-McCarthy (thomas.padron-mccarthy@oru.se)

Det här materialet, som ursprungligen skrevs 1994 för kursen Programmering i C vid Linköpings universitet, utgör en kort beskrivning av några aspekter på hur man programmerar. Bland annat handlar det om vad man brukar kalla "kodningsstil". Tänkt målgrupp är främst studenter på inledande eller senare programmeringskurser.

Mycket är mina personliga synpunkter, och det finns ibland alternativ till vad jag skrivit.

Jag har använt C i exemplen, men det mesta som står här gäller vare sig man programmerar i C eller i något annat språk, som till exempel Java eller Lisp. Exemplen kan lätt översättas.

Se upp med att en del av "C-koden" inte är helt korrekt C. Bland annat har jag använt svenska tecken i identifierare, vilket man inte får enligt C-standarden, och på ett par ställen är det lite pseudokod inblandad.

Sammanfattning

Det här materialet handlar inte om hur man skriver program så att de fungerar, utan så att källkoden blir lättläst och enkel att förstå. Vi lär oss tre grundregler, som man ska tänka på när man programmerar:

  1. Skriv för människor och inte bara för datorn!
  2. Skriv vad du menar!
  3. Krångla inte till din kod i onödan!

Varför?

Ja, varför? Det här handlar alltså inte om hur man skriver program så att de fungerar, utan så att källkoden ser snygg ut. Och vad sjutton spelar det för roll hur källkoden ser ut, så länge programmet fungerar?

Jo:

Det är ganska ovanligt att en programmerare sätter sig ner med en tom fil och börjar skriva ett nytt program helt från början. I stället bygger man vidare på existerande program, eller modifierar och rättar dem. Därför består "programmering" minst lika mycket av att läsa programkod som att skriva den.

Att programmera innebär därför att man kommunicerar, och inte i första hand med datorn utan i stället med andra människor. Datorn ska förstås också läsa programmet, när den kompilerar det, men det tar kanske en halv sekund. Andra programmerare kan komma att jobba vidare i dagar, månader och år med din programkod. Då gäller de att de begriper vad du skrivit! (Och dessa "andra programmerare" kan också vara du själv, om två år när du glömt hur du tänkte när du skrev det där gamla programmet.)

Dessutom är det lättare att få programmet rätt om man skriver det på ett enkelt och tydligt sätt, utan onödiga krångligheter.

Innehåll

Rubrikerna kan också användas som sammanfattning av innehållet.
  1. Använd meningsfulla och rättvisande namn på variabler och annat!
  2. Kommentera lagom mycket, och kommentera rätt saker!
  3. Använd symboliska konstanter och namngivna datatyper!
  4. Använd inte globala variabler i onödan!
  5. Återanvänd inte variabler!
  6. Tänk på hur du använder loopar!
  7. Loopar och if-satser (och funktioner) ska vara korta!
  8. Dela upp programmet i funktioner!
  9. Undvik att upprepa kod!
  10. Använd strukturerad programmering!
  11. Formatera programmet så det blir lättläst!
  12. Skriv för människor och inte bara för datorn!
  13. Följ konventioner!
  14. Optimera inte (än)!
  15. Det är bra med portabilitet!
  16. Modularisera och abstrahera!

1. Använd meningsfulla och rättvisande namn på variabler och annat!

Ett av de viktigaste och enklaste sätten att göra ett program begripligt är att kalla saker och ting för vad de är, i stället för något annat. Följ därför följande enkla regler!
  1. Använd meningsfulla namn! Om vi har en variabel som anger antalet kunder i ett kundregister bör vi inte kalla den x eller n, utan kanske antal_kunder. Möjligt undantag: åtminstone i en kort (några få rader) och därigenom lätt överblickbar loop brukar man ofta använda ett kort namn som i för kontrollvariabeln. Exempel:
            for (i = 0; i < antal_tecken; ++i)
                    putchar(personens_namn[i]);
    
    Men om man har flera loopar i varandra kan det bli rörigt med loopvariablerna i, j, k och l, så hitta helst på "riktiga" namn då.
  2. Undvik obegripliga förkortningar! En funktion som skriver ut alla kunderna på skärmen ska förstås inte heta blaha, men den bör inte heller ha en kryptisk förkortning som skrk. Kalla den skriv_kunder!
  3. Namnen får inte vara missvisande! Riktigt illa blir det när man har namn som är meningsfulla men som betyder fel sak - till exempel om vi kallade funktionen ovan skriv_kund (i stället för skriv_alla_kunder eller skriv_kunder), eller om vi har en variabel antal_kunder som anger antalet kunder i registret minus ett!
  4. Alla namn ska vara meningsfulla och rättvisande! Punkterna ovan gäller förstås inte bara namnen på variabler och funktioner, utan också namnen på konstanter, datatyper, filer, hela program och så vidare.
Tips: Om du tycker det är jobbigt att skriva långa variabelnamn (som antal_tecken_i_bufferten), så har många programmeringsomgivningar funktioner för att fylla i dem. Visual Studio har IntelliSense och Emacs har kommandot ESC-/.

2. Kommentera lagom mycket, och kommentera rätt saker!

Att skriva bra kommentarer i program är svårt. I mycket små program är kommentarerna kanske den enda beskrivning som finns av hur programmet är gjort, och då är det förstås extra viktigt att kommentarerna är bra skrivna. Tänk dig att du ska sätta dig in ett program som nån annan skrivit, till exempel för att rätta fel eller göra andra modifieringar -- och skriv kommentarer utifrån vad du själv skulle vilja veta i den situationen!

Förklara vad som händer. Exempel:

        /* Den här funktionen sparar hela kundregistret på en fil. */
Förklara hur där det behövs. Exempel:
        /* Vi letar efter den sökta varan med binärsökning. */
Förklara allt konstigt. Exempel:
        /*  Funktionen get_smurfs() returnerar en pekare till den
         *  sist inlästa smurfen, så vi måste leta bakåt i listan
         *  till den första posten innan vi skriver ut dem!
         */
Särskilt viktigt är det att ange begränsningar och kända fel. Exempel:
        /*  Den här funktionen klarar bara att sortera arrayer med
         *  högst 40 element.
         *  Sorteringen är inte stabil, dvs element med lika
         *  nycklar kan komma i fel ordning.
         */
Man ska inte förklara på detaljnivå. Dåligt exempel:
        i += 2;         /* Öka i med 2 */
Undvik kommentarer som redan är uppenbara av själva koden! Dåligt exempel:
        int antal_kunder;       /* Antal kunder */
Saker som man nästan alltid bör kommentera:

  1. Funktioner och metoder (vad de gör, vad de returnerar, eventuellt annat som är viktigt)
  2. Deras parametrar (vad de betyder, krav och begränsningar)
  3. Variabler (vad de används till)
  4. Datatyper, inklusive klasser (vad de betyder)
  5. Hela filen (vad den innehåller)

De viktigaste kommentarerna är de översiktliga och förklarande, som beskriver vad ett stort kodavsnitt (kanske hela programmet) gör, och varför det finns och är skrivet på just det sättet.

3. Använd symboliska konstanter och namngivna datatyper!

Förutom att programmet blir lättare att läsa blir det också enklare att göra ändringar, eftersom man bara behöver ändra på ett ställe. Dåligt:
        char min_bils_märke[19];
Bättre (i alla fall om man använder längden på bilmärken på fler ställen):
        #define MAX_TECKEN_I_BILMäRKEN  18
        char min_bils_märke[MAX_TECKEN_I_BILMäRKEN + 1];
Ännu bättre kan det vara att införa en datatyp som heter bilmärke, som man sen kan använda:
        bilmärke min_bils_märke;
(Men av skäl som är speciella för hur språket C fungerar är det förmodligen olämpligt att låta datatypen utgöras av en array.)

4. Använd inte globala variabler i onödan!

Använd inte globala variabler i onödan. Använd i stället parametrar och returvärden för att skicka värden till och från funktioner.

Det här betyder inte att du aldrig ska använda globala variabler. Egentligen är det så att en variabel ska definieras "så nära där den används som möjligt", och att det inte ska gå att komma åt den på andra ställen i programmet.

En variabel som bara används inuti en funktion ska förstås vara lokal i den funktionen. I C kan man ha lokala variabler som behåller sitt värde mellan anrop (de deklareras som static).

5. Återanvänd inte variabler!

Om du i en funktion behöver jobba först med antalet kunder och sen med antalet varor, så definiera två variabler (till exempel kallade antal_kunder och antal_varor). Du vinner inget på att bara definiera en variabel (kallad till exempel antal eller antal_kunder_eller_varor) och använda den för bägge ändamålen. Sådana saker fixar kompilatorn åt dig!

6. Tänk på hur du använder loopar!

I C finns tre olika konstruktioner för repetition (loopar) - for, while och do ... while. Vilken man väljer är ibland en ren smaksak. Så här tycker jag:

Om antalet varv är känt redan när man går in i loopen, brukar man oftast använda en for-loop:

        for (i = 0; i < antalet_varv_vi_ska_köra; ++i)
                gör_nånting();
I C går array-index från 0 till antalet element i arrayen minus ett, och bland annat därför brukar man i loopar, som ska köras N stycken varv, alltid skriva
        for (i = 0; i < N; ++i)
                gör_nånting();
i stället för till exempel
        for (i = 1; i <= N; ++i)
                gör_nånting();
Om vi inte från början vet hur många varv loopen ska köras, kan man använda en while-loop:
        while (det_är_inte_slut_än(nånting))
                gör_nånting();
En del C-programmerare använder for-loopar även i det här fallet, vilket går bra eftersom varje while-loop i C enkelt kan skrivas om som en for-loop (och tvärtom), vilket inte är sant i till exempel Pascal. Ett bra exempel är när man vill stega igenom andra linjära datastrukturer än arrayer, till exempel en länkad lista:
        for (p = min_lista; p != NULL; p = p->next)
                skriv_element(p);
Om loopen alltid ska köras minst en gång, och vi vill köra loopen ett varv innan testen, kan man använda en do-while-loop:
        do
                gör_nånting();
        while (det_är_inte_slut_än(nånting));
Du kommer antagligen aldrig att behöva använda continue-satsen. Den är onödig och rör bara till koden.

Försök undvika break-satsen i loopar. Vid vissa tillfällen är den dock användbar och ger tydligare kod.

7. Loopar och if-satser (och funktioner) ska vara korta!

Loopar och if-satser ska vara korta, helst bara några rader och nästan aldrig längre än en A4-sida. Det är mycket svårt att bläddra fram och tillbaka i en alltför lång loop. Dela upp i funktioner!

8. Dela upp programmet i funktioner!

Skriv små och enkla funktioner. Helst ska varje funktion bara göra en sak. Denna "enda sak" kan förstås vara svår och komplicerad att utföra, och kräver kanske tusentals rader kod. Ett exempel kan vara funktionen välj_nästa_drag i ett schackprogram, eller ställ_diagnos i ett expertsystem som diagnosticerar sjukdomar. Den måste dock kunna betraktas som "en sak", och alla de tusentals raderna kod ska förstås inte ligga i samma funktion. Dela upp i många funktioner!

Tumregel:

Det ska gå att beskriva vad funktionen gör på en enda rad, exempelvis "sortera en array av heltal i nummerordning". Om beskrivningen i stället blir någonting i stil med "sortera en array av heltal i nummerordning, och skriv sen ut den, men om flaggan foo är satt ska den först summeras och summan läggas i variabeln fum, och sen..." har du antagligen lagt in för mycket saker i funktionen som egentligen inte hör ihop. Dela i så fall upp funktionen i dess logiska delar!

9. Undvik att upprepa kod!

Försök att strukturera programmet så att du inte behöver upprepa samma programkod på flera ställen. Dels blir det onödigt mycket att läsa (och skriva), och dessutom måste du komma ihåg att ändra på alla ställena om du ska ändra något. Samla den i en funktion i stället, som du anropar från de ställen där du annars upprepade samma kod.

Ibland kan man åstadkomma detta genom att bryta ut den upprepade koden och lägga i en funktion, som sen anropas från flera ställen, och ibland räcker det med lite omflyttning. Om man till exempel har programsnutten

        if (y == 0) {
                skriv_summan(x, y);
                skriv_differensen(x, y);
                skriv_produkten(x, y);
                printf("Går inte att dela med noll!\n");
        }
        else {
                skriv_summan(x, y);
                skriv_differensen(x, y);
                skriv_produkten(x, y);
                skriv_kvoten(x, y);
        }
med upprepningar av anropen till skriv_summan med flera, så kan man göra om den till
        skriv_summan(x, y);
        skriv_differensen(x, y);
        skriv_produkten(x, y);
        if (y == 0)
                printf("Går inte att dela med noll!\n");
        else
                skriv_kvoten(x, y);

10. Använd strukturerad programmering!

Använd strukturerad programmering! Det betyder (ungefär) att du ska använda de konstruktioner för loopar och val (while, for, if, switch etc.) som finns i språket, och undvika hopp med goto, break, continue och longjmp. Dessa hoppkonstruktioner är inte förbjudna, men du ska ha goda skäl om du använder dem!

Ett exempel där goto-satsen kan användas:

        for (x = 0; x < x_max; ++x)
            for (y = 0; y < y_max; ++y)
                for (z = 0; z < z_max; ++z)
                    for (t = 0; t < t_max; ++t)
                        if (gör_nånting(x, y, z, t) == FELKOD)
                            goto det_blev_fel;
        printf("Det gick bra.\n");
        ...

    det_blev_fel:
        printf("Ajajaj. Det där gick inte bra.\n");
        ...
En del C-programmerare tycker också att man ska vara försiktig med return-satsen, eftersom den ju fungerar som ett "hopp" ut ur en funktion.

11. Formatera programmet så det blir lättläst!

När det gäller formatering av koden, dvs hur många steg man ska indentera, ifall { och } ska stå på egna rader och så vidare, så välj en stil som passar dig, och håll dig till samma i hela programmet. Det finns många olika stilar, alla med sina fördelar. När du ändrar i ett program som någon annan skrivit, använd samma stil som det programmet är skrivet med.

Som exempel kommer här tre olika sätt att skriva en if-sats:

        if (nånting > nånting_annat) {
                gör_nånting();
                och_en_sak_till();
        }

        if (nånting > nånting_annat)
        {
            gör_nånting();
            och_en_sak_till();
        }

        if (nånting > nånting_annat)
            {
                gör_nånting();
                och_en_sak_till();
            }
Det finns program som indenterar och formaterar koden åt dig. Till exempel kan du skriva ESC-X indent-region i Emacs, eller köra programmet indent på Unix, men inget formateringsprogram kan göra ett lika bra jobb som du själv. Använd mellanslag och tomrader för att öka läsbarheten genom att gruppera och dela upp ditt program. Dåligt exempel:
        if(x*y>.1&&(z+2*w<0||z+2*w>10))
Det blir ofta bättre med några strategiskt utplacerade mellanslag. Bra exempel:
        if (x*y > 0.1 && (z+2*w < 0 || z+2*w > 10))
Men stoppa inte heller bara planlöst in en massa mellanslag överallt! Dåligt exempel:
        if ( x * y > 0.1 && ( z + 2 * w < 0 || z + 2 * w > 10 ) )
Var noggrann! Om det plötsligt kommer ett par tomma rader mitt i en massa kod, så tror man förstås att det är nån sorts gräns mellan olika delar av programmet. Det kan bli förvirrande om det i stället beror på att du tryckte på RETUR några gånger av misstag och sen inte orkade ta bort de extra raderna.

12. Skriv för människor och inte bara för datorn!

Skriv program för människor, inte för datorn! När du skriver ett program, tänk på dem som ska läsa det! En stor del av programmeringsarbetet i världen består i att ändra i gamla program som någon annan har skrivit.

Säg vad du menar, och krångla inte till det! Många saker går att skriva på flera olika sätt. Välj då det som tydligast visar hur du tänkt. Till exempel så är

        if (antal_bilar == 0) { gör nånting... }
bättre än
        if (!antal_bilar) { gör nånting... }
eftersom det du gör är ju att kolla om antalet bilar är noll, inte nån sorts logisk operation "om inte antalet bilar, så..."!

13. Följ konventioner!

I många programspråk finns olika konventioner som man brukar följa. Det är inte förbjudet att bryta mot dem, men du ska ha goda skäl för att göra det. I C har vi till exempel konventioner för vad som ska skrivas med stora bokstäver. Makron och konstanter som definierats med preprocessorn (dvs med #define) brukar skrivas med stora bokstäver:
        #define MAX_ANTAL_SMURFER       22
        #define SMURFA(a, b)            { while (a) smurfa(b); }
"Funktionsliknande" makron brukar man dock ofta skriva med små bokstäver:
        #define addera(x, y)            ((x)+(y))
Ofta skriver man också datatyper som deklarerats med typedef med stora bokstäver:
        typedef unsigned int SMURFNUMMER;

14. Optimera inte (än)!

Om du inte vet vad som menas med optimering kan du hoppa över det här avsnittet.

En del programmerare lägger ner stor tid på att skriva "effektiva" program, dvs (oftast) program som går snabbt att köra. Vi brukar kalla detta att optimera, eller hand-optimera, sitt program.

Om man anstränger sig för att skriva snabba program, har man ju infört en extra svårighet, förutom att få programmet att fungera. Programmet blir krångligt och svårläst, eftersom man ofta ägnar sig åt olika "trix och fix" för att öka snabbheten. Det är också i de flesta fall onödigt att optimera, och även i de fall där det är motiverat är det lätt att man optimerar på fel sätt, kanske till och med så att programmet går långsammare!

Ytterligare en nackdel med att optimera sina program är att de trix och fix man använder kanske inte alls fungerar på andra datorer och andra kompilatorer än just den du utvecklar programmet i, så om ditt program senare ska köras på en annan dator, så kanske det måste skrivas om.

Därför ska vi nu lära oss två regler för optimering:

  1. Gör det inte!
  2. Gör det inte än!
Detta betyder att oftast behöver man inte alls optimera sitt program, och om man trots allt måste göra det (när programmet faktiskt går för långsamt) bör man vänta i det längsta med optimeringen, så att man verkligen vet att, vad och hur man ska optimera!

Se först till att programmet är korrekt (dvs att det fungerar) och robust (dvs att det klarar även felaktiga och konstiga inmatningar utan att få spader eller krascha), samt att att koden är lättbegriplig. Optimera inte!

Om du sen tycker att programmet går för långsamt, låt kompilatorn försöka generera effektivare kod. Kompilera om programmet med flaggan -O eller motsvarande. Optimera inte - låt kompilatorn göra det!

Om det i alla fall går för långsamt, kan du börja tänka på att optimera för hand. Gör då följande:

  1. Ta reda på var du ska optimera, dvs var i programmet går det åt mest tid? Det finns särskilda verktyg som du kan använda för att mäta hur lång tid som går åt i olika delar av programmet.
  2. Optimera på hög nivå (algoritmer och datastrukturer). Om du byter sorteringsalgoritm från bubblesort till quicksort kanske körtiden minskar från en timme till en sekund (jodå, det är sant - titta i en bok om sorteringsalgoritmer om du inte tror mig!).
  3. Först i sista hand ska du börja med lågnivåoptimering, dvs trix och fix till exempel med pekare och bitoperatorer. Sånt kan du göra när du redan har de snabbaste och smartaste datastrukturer och algoritmer som finns, och programmet fortfarande är för långsamt, och du dessutom har tagit reda på var du ska optimera.
Ett exempel:

Det förekommer att C-programmerare skriver om array-kopieringar, som vanligen ser ut som

        int array1[ANTAL_ELEMENT], array2[ANTAL_ELEMENT];
                ...
        int i;
                ...
        for (i = 0; i < ANTAL_ELEMENT; ++i)
                array1[i] = array2[i];
till någonting i stil med
        int array1[ANTAL_ELEMENT], array2[ANTAL_ELEMENT];
                ...
        register int *array1p, *array1end, *array2p;
                ...
        array1p = array1;
        array1end = array1 + ANTAL_ELEMENT;
        array2p = array2;
        while (array1p < array1end)
                *array1p++ = *array2p++;
Den senare versionen antar de ska gå snabbare. I själva verket kommer en del kompilatorer att generera exakt samma kod för båda skrivsätten, och en del kompilatorer faktiskt långsammare kod för den andra konstruktionen. Om man dessutom tänker på att de komplicerat programmet i onödan så det tar längre tid att skriva, och med större risk för fel, och att programmet blir svårare för andra (och dem själva) att förstå, och att tiden för att köra den här loopen ändå kanske bara utgör en hundradels procent av exekveringstiden för hela programmet, kan man undra vad vitsen egentligen är.

Det här betyder inte att man alltid ska strunta i all effektivitet. Även ett enkelt program kan göras så långsamt och minneskrävande att det blir helt oanvändbart, om man bara väljer olämpliga datastrukturer och långsamma algoritmer. Du bör redan från början välja datastrukturer och algoritmer som passar för problemet. Lågnivåeffektiviteten är dock mindre viktig, och hanteras oftast bättre av kompilatorn.

Sammanfattning (som gäller både vid optimering och annars):

  1. Skriv för människor och inte bara för datorn!
  2. Skriv vad du menar!
  3. Krångla inte till din kod i onödan!

15. Det är bra med portabilitet!

Portabilitet eller flyttbarhet betyder att du kan kompilera och köra ditt program på andra system, eller med andra kompilatorer, än den eller de som det ursprungligen var skrivet för, utan att du behöver arbeta så mycket med att skriva om programmet. Det kan handla om att flytta från Borland till Visual Studio, eller från Windows till Linux.

Portabilitet kan alltså vara arbetsbesparande, och bör eftersträvas. Den åstadkommes främst genom att man skriver vad man menar, och undviker maskin- eller systemberoende optimeringar och andra "trix och fix". Undvik också att skriva program som är beroende av saker som egentligen är odefinierade i språket du skriver i, men som ändå alltid brukar fungera på samma sätt just i den miljö du utvecklar programmet, till exempel beräkningsordning i uttryck, eller interna lagringsformat.

Om man vill ha ett program som är lätt att flytta till andra system, bör man dela upp programmet så att all den programkod som måste ändras finns samlad på ett ställe.

16. Modularisera och abstrahera!

De här avsnittet handlar om modularisering och abstraktion, och handlar kanske mer om programmeringsmetodik än om kodningsstil. De här två begreppen är dock så grundläggande för "hur man programmerar" att jag i alla fall vill ta med dem här.

1. Modularisera!

Modularisering innebär att vi delar upp ett stort problem i flera små delproblem, som vi sen löser var för sig. Det är lättare att lösa tre små problem än att lösa ett problem som är tre gånger så stort. (Fånig jämförelse: Vad vill du helst göra: hoppa en meter högt tre gånger, eller hoppa tre meter högt en gång?) Om vi gör uppdelningen på ett bra sätt, kan vi ofta lösa varje delproblem utan att behöva tänka på hur det hänger ihop med de andra delproblemen.

När vi skriver ett program kan vi till exempel dela upp det i flera delar, och sen kan vi skriva varje del av programmet för sig. Vi kontrollerar att varje del fungerar som den ska, och sen slår vi ihop alla delarna till ett (förhoppningsvis) fungerande program.

Man brukar tala om att varje modul ska ha hög "styrka" och att "kopplingen" mellan modulerna ska vara låg. Det betyder ungefär att varje modul ska göra en sak (men den enda saken kan vara komplicerad), och att den inte ska vara beroende av hur andra moduler ser ut inuti. Jämför med avsnittet "Dela upp programmet i funktioner!".

Ytterligare en fördel med modularisering är att du kan återanvända en modul du skrivit, till exempel genom att använda den till flera olika saker i samma program, eller kanske i andra program som du skriver senare.

2. Abstrahera!

Abstraktion är ett begrepp som ibland är lite svårare att förklara. Med "abstrakt" menar man här ungefär "mer likt hur en människa tänker än hur datorn arbetar". Abstraktion kan göras på olika sätt, men i programmeringssammanhang är ett av de vanligare att man arbetar med något vi kallar "abstrakta datatyper".

Man kan se en abstrakt datatyp som ett sorts skal. Innanför skalet finns alla implementationsdetaljerna, till exempel om dataobjekten lagras som arrayer eller poster, och hur de funktioner som arbetar med dem är skrivna. Utanför skalet varken vill eller får man bry sig om dessa detaljer.

Exempel på en abstrakt datatyp kan vara en "mängd av heltal". Det spelar ingen roll för oss som använder datatypen "mängd av heltal" om den egentligen är en länkad lista, en array eller något annat, det enda vi bryr oss om är att den fungerar som en mängd, till exempel så att vi kan beräkna unionen eller snittet av två mängder.

De funktioner som arbetar med den abstrakta datatypens inre struktur kallar vi "primitiva funktioner" eller "primitiver".

Det kan finnas flera abstraktionsnivåer, inte bara en. En abstrakt datatyp kan implementeras med hjälp av andra abstrakta datatyper - till exempel klockslag som består av en timme och en minut. I de primitiva funktionerna för datatypen klockslag, till exempel skapa_klockslag eller är_detta_ett_klockslag måste man förstås känna till och använda att ett klockslag består av en timme och en minut som sitter ihop på något sätt, kanske i en lista eller an array. Men i klockslags-primitiverna är ju timme och minut fortfarande abstrakta datatyper, som ska hanteras endast via sina primitiver, så där får man inte gå in och gräva med pekare (eller med car och cdr, om vi får prata Lisp ett tag).


Thomas Padron-McCarthy (thomas.padron-mccarthy@oru.se), 2 april 2006