Link Search Menu Expand Document (external link)

AJ 1.5 Funktionell programmering i JavaScript

Table of contents


Vad är funktionell programmering?

JavaScript är ett sk multi-paradigm-language, och kan skrivas enligt flera olika programmeringsparadigmer. Ett programmeringsparadigm är i huvudsak en samling regler som du följer när du skriver kod. En sån paradigm är funktionell programmering. 1

Deklarativ paradigm

I imperativ programmering så talar vi om exakt hur programmet ska göra för att uppnå någonting. I deklarativ programmering talar vi om vad vi vill ska hända, inte hur det ska göras. Funktionell programering är en deklarativ programmeringsparadigm. 1

Funktionell programmering bygger i hög grad på användingen av rena (pure) och isolerade funktioner. En pure funktion har inga sidoeffekter.

Purity

Hanterar inte något utanför sig själv, returnerar alltid ett värde, är oföräderlig, kan inte påverkas utifrån. Det går alltid att veta vilket output det blir vid ett givet input, den går att koppla ihop med andra funktioner.


Vad är INTE funktionell programmering?

  • Allt som är imperativt
  • Allt som direkt manipulerar variabler (viktigt att behålla state i funktionell programmering)
  • Allt med risk för sidoeffekter
  • Loopar - while, do..while, for, for...in, for...of etc
  • let och var (de går att ändra värde på)
  • Objekt mutationer - t.ex. o.key = ‘value’
  • Array mutationer - pop, shift, push, sort
  • Map mutationer - clear, delete, set
  • Set mutationer - add, clear, delete

Lamdakalkyl (λ-kalkyl)

λ-kalkyl är ett formellt system som skapades för att undersöka funktioner och rekursion. Utvecklades av Alonzo Church på 30-talet, fick genombrott efter -69 då Dana Scott tagit fram den första konsistenta matematiska modellen för λ-kalkyl. Är den matematiska grunden för många funktionella programmeringsspråk och används för att kunna göra de saker som inte anses vara funktionella (loopar, mutationer etc… se ovan).

Regler för funktioner i λ-kalkyl

  • Funktioner definieras alltid som anonyma
  • Funktioner ör enställiga (unary), de tar bara in en parameter. Om funktionen behöver mer än en parameter, så tas de övriga parametrarna och returneras via en ny funktion. Dela upp alla responsibility i den stora komplexa funktionen till flera små funktioner som tar en parameter var. Detta kallas inom funktionell programmering och λ-kalkyl för currying (efter Haskell B. Curry)
  • First class-funktioner kan användas som inmatning, funktioner kan också returnera funktioner

Higher order functions

För att enklare förstå vad higher order functions är, så kommer en liten genomgång av de olika typer av funktioner som finns i JavaScript.

First class functions

I JS är alla funktioner s.k. first class citizens, vilket innebär att de kan behandlas som vilken variabel som helst. Funktioner kan tilldelas som värden till variabler, returneras från andra funktioner coh skickas som argument till andra funktioner. 2

Exempel

En funktion sparad som ett värde i en variabel

const greeting = () => {
  console.log('Hello World!');
}
greeting();

Callback functions

Callback funktioner skickas till andra funktioner som argument, och anropas sen av den funktions som de har skickats till. De kallas sen när funktionen till vilken de skickades som argument kallas/invokas. 3

Exempel

Callback funktionen är den anonyma funktionen som vi skickar in i promptInput() som argument.

function promptInput(callbackFn) {
  const name = prompt('Please enter your name');
  callbackFn(name);
}

promptInput(name => console.log(`Hello ${name}!`));

Asynkrona funktioner

Typiska asynkrona funktioner har inget namn och kan inte återanvändas. De skrivs oftast när vi bara behöver utföra en grej en gång och på ett ställe. 2

Asynkrona funktioner returnerar ett Promise, och denoteras (oftast) med nyckelorden async och await. Används ofta vid t.ex. API-anrop.

Higher order functions

Higher order functions är funktioner som tar emot andra funktioner som argument eller returnerar en funktion. 2 Det är bland annat dessa funktioner som gör JavaScript så optimalt för funktionell programmering.

Nedan följer några exempel på de mest användbara higher order functions inbyggda i JavaScript.

.map()

Array-metod som tar en callback-funktion som argument. För varje element i arrayen anropas funktionen, sen returneras en ny array med resultet.

const array = [1, 2, 3, 4];
const newArray = array.map(x => x * 2);

console.log(newArray); // [2, 4, 6, 8]

.filter()

Array-metod som tar en callback-funktion som argument. Callback-funktionen anropas för varje element i arrayen och returnerar en booelan. När alla element anropats returnerar .filter() en ny array med bara de element där callback-funktionen returnerat true.

const array = [1, 2, 3, 4];
const newArray = array.filter(num => num > 2);

console.log(newArray); // [3, 4]

.reduce()

Array-metod som tar en callback-funktion som argument, som sen anropas för varje element i arrayen. Callback-functionen tar två argument, dels nuvarande element och dels returvärdet från förra anropet. När .reduce() gått igenom alla element så har de reducerats till ett enda värde som sen returneras.

const array = [1, 2, 3, 4];
const callbackFn = (returnValue, currentValue) => returnValue + currentValue;

console.log(array.reduce(callbackFn)); // 10

.forEach()

Array-metod som tar en callback-funktion som argument. Callback-funktionen exekveras för varje element i arrayen. Ersätter ofta for...-loopar på ett väldigt smidigt sätt.

const array = [1, 2, 3, 4];

array.forEach(element => console.log(`${element} Mississippi`));

// '1 Mississippi'
// '2 Mississippi'
// '3 Mississippi'
// '4 Mississippi'

Rekursion

En rekursiv funktion är en funktion som kallar på sig själv, tills ett visst villkor har uppnåtts (annars skulle det loopa i en evighet). Generellt fungerar det ungefär såhär: 4

function recurse() {
  if(condition) {
    recurse();
  } else {
    // stop calling recurse()
  }
}
recurse();

I allmänhet så används rekursova funktioner för att dela upp ett stort problem i mindre. De används ofta i t.ex. sorteringsalgoritmer.


Referenser