AD1, FP, PK1, PK2, PM1: Kodningsstandard

Specifikationer

Varje funktion skall föregås av en kommentar med dess specifikation. Det gäller oavsett om den är deklarerad lokalt eller globalt, är "stuvad" (curried) eller inte, är angiven i uppgiftsbeskrivningen eller påhittad av dig.

Det enda undantaget från ovanstående gäller anonyma funktioner som ges som argument till en annan funktion. Där slipper du skriva specifikation, men å andra sidan skall en sådan funktion vara mycket enkel. Om den inte är det så skall du inte använda en anonym funktion utan namnge den.

Kommentaren skall vara utformad på följande sätt:

(* funktionsnamn argument
   TYPE: argumenttyp -> resultattyp
   PRE:  ... pre-condition på argumenten ...
   POST: ... beskrivning av resultatet ...
   EXAMPLES: ... representativa exempel på anrop ...
*)

Observera att specifikationen knappast kan vara användbar om inte samtliga argument förkommer i post-condition (eller side-effects, om det är aktuellt - se nedan).

Varje värde i en abstrakt datatyp eller modul skall föregås av en kommentar med dess specifikation. Kommentaren skall vara utformad på följande sätt:

(* valuenamn
   TYPE:  typ
   VALUE: ... beskrivning ...
*)

Lösningen av en uppgift - vare sig det gäller på laboration, inlämningsuppgift eller tentamen där inte alla funktioner och värden har en specifikation med ovanstående innehåll kan komma att underkännas! Detta oberoende av ifall lösningen i övrigt skulle vara fullständigt korrekt.

Identifierare

Varje funktionsnamn och värdenamn skall beskriva det namngivna objektet.

Varje identifierare skall börja med liten bokstav. Om man vill ha flera ord i identifieraren så stapla dem på varandra och låt alla ord utom det första börja med stor bokstav. Använd inte understrykningstecken (`_') mellan ord.

Exempel:

   maxValue
   endOfTheGame

Rekursiva funktioner

Varje rekursiv funktion skall ha en rad i funktionsspecifikationen som anger rekursionsvarianten. T.ex. så här:

  VARIANT: ...

Lösningen av en uppgift - vare sig det gäller på laboration, inlämningsuppgift eller tentamen där inte alla rekursiva funktioner har en kommentar med ovanstående innehåll kan komma att underkännas! Detta oberoende av ifall lösningen i övrigt skulle vara fullständigt korrekt.

Sidoeffekter

Varje funktion med sidoeffekter skall ha en rad i funktionsspecifikationen som beskriver sidoeffekterna. T.ex. så här:

  SIDE-EFFECTS: ...

Lösningen av en uppgift - vare sig det gäller på laboration, inlämningsuppgift eller tentamen där inte alla funktioner med sidoeffekter har en kommentar med ovanstående innehåll kan komma att underkännas! Detta oberoende av ifall lösningen i övrigt skulle vara fullständigt korrekt.

Indentering

Layout och indentering av funktionsdeklarationer skall göras på följande vis

fn pattern1 => expression1
   ...
 | patternN => expressionN

Layout och indentering av if-then-else-uttryck skall göras på följande vis:

   ...
   if booleanExpression then
       expression1
   else 
       expression2
   ...

Om ytterligare if-uttryck följer efter ett else bör layout och indentering göras på följande vis:

   ...
   if booleanExpression1 then
       expression1
   else if booleanExpression2 then
       expression2
   ...
   else
       expressionN
   ...

Layout och indentering av case-uttryck skall göras på följande vis:

case expression of
     pattern1 => expression1
     ...
   | patternN => expressionN

Layout och indentering av let-uttryck skall göras på följande vis:

   ...
   let
       declaration1
       ...
       declarationN
   in 
       expression
   end
   ...

Layout och indentering av lokala deklarationer skall göras på följande vis:

   ...
   local
       declaration11
       ...
       declaration1N
   in 
       declaration21
       ...
       declaration2M
   end
   ...

Det exakta antalet blanktecken i indenteringen är inte viktig, men all indentering måste vara konsekvent, dvs varje uttryck inom "..." ovan måste börja lika långt från vänsterkanten utom där indenteringen skall ändras enligt ovanstående regler.

Indentering av andra uttryck än de som beskrivs ovan skall göras efter bästa förstånd. Titta gärna på program i kursboken och på OH-bilderna från föreläsningarna för ideer.

Varför

Varför kräver vi att du skall utforma din kod på detta sätt? Jo för att:

  • Det visar att du har tänkt igenom vad funktionen skall göra och hur
  • Det underlättar för assistenterna att rätta (och de har jobb så det räcker...)
  • (Bra) programutvecklingsföretag har i allmänhet kodstandarder.

Exempel

(* myMax (a,b)
   TYPE: int * int -> int
   PRE:  (none)
   POST: the largest value among a and b
   EXAMPLES: myMax ( 2, 5) =  5
             myMax (~2,~5) = ~2
*)
fun myMax (a,b) =
    if a > b then
      a
    else 
      b
(* fact n
  TYPE: int -> int
  PRE:  n >= 0
  POST: the factorial of n
  VARIANT: n
  EXAMPLES: fact 0 = 1
            fact 3 = 6
*)
fun fact 0 = 1
  | fact n = n * fact (n-1)
abstype 'a stack = Stack of 'a list
with
  (* emptyStack
     TYPE:  'a stack
     VALUE: the empty stack
  *)
  val emptyStack = Stack []
  (* push v S
     TYPE : 'a -> 'a stack -> 'a stack
     PRE:  (none)
     POST: the stack S with v added as top element
  *)
  fun push v (Stack S) = Stack (v::S)
  ...
end