Pure functies en expressies
Home

Pure functies en expressies

Pure functies en expressies

Een zuivere functie is een functie die, gegeven dezelfde invoer, altijd hetzelfde resultaat zal retourneren zonder waarneembare neveneffecten. Dat wil zeggen dat de retourwaarde alleen afhankelijk is van de parameters en dat er geen veranderingen buiten de functie plaats vinden. Het resultaat van zo’n functie is dus altijd reproduceerbaar. Denk aan een black box met een invoer en uitvoer.

Beschrijving

De formele wiskunde van het beschrijven van de logica ligt aan de basis van het functioneel programmeren, namelijk de lambda calculus. Wiskundigen beschrijven graag programma's als transformaties van data. En dat brengt ons naar het eerste concept, namelijk pure functies. Pure functies zijn functies zonder neveneffecten. Pure functies zijn alleen afhankelijk van de invoer van de functie en produceren altijd exact dezelfde uitvoer voor dezelfde input.

Programmeertalen komen in verschillende stijlen. Talen zoals Go en C worden procedureel genoemd omdat hun basiscomponent de procedure is. Talen als Java en SmallTalk zijn objectgeoriënteerd omdat hun belangrijkste component het object is. Beide benaderingen zijn imperatief omdat ze een beroep doen op instructies die afhankelijk zijn van de machine-staat. Een imperatief programma voert een reeks opdrachten uit die interne toestand van het programma steeds weer veranderen.

Functionele programmeertalen zijn gebaseerd op uitdrukkingen. Uitdrukkingen, of beter, pure uitdrukkingen, hebben geen staat omdat ze alleen maar een waarde berekenen.

Eric Elliott, Master the JavaScript Interview: What is a Pure Function?, Mar 26 2016

Referentiële transparantie

De code hieronder is een zuivere functie omdat de functie

  1. niet afhankelijk is van een of andere toestand (state) buiten de functie;
  2. niets wijzigt aan de toestand buiten de functie;
  3. altijd dezelfde waarde retourneert voor dezelfde input;
  4. de functie kan worden vervangen door de inhoud van de functie of door de geretourneerde waarde (substitutie);
// pure function
function add(a, b) {
  return a + b;
}

De code hieronder is een onzuivere functie omdat de functie afhankelijk is van een wijzigbare toestand (mutable state) buiten de functie.

// impure function
var maximum = 120;
var canWithdraw = function(amount) {
  return  amount > maximum; // maximum can be changed outside function
};

Als we de maximum variabele binnenin de functie plaatsen wordt de functie zuiver en zijn we er zeker van dat de functie het maximum afhaalbare bedrag steeds op dezelfde manier zal checken.

// pure function
var canWithdraw = function(amount) {
  var maximum = 120;
  return  amount > maximum;
}

Ze veranderen dus niet de status van iets dat buiten hun bereik ligt en zij ze zijn niet afhankelijk van gegevens die buiten hun bereik veranderd kunnen worden. Als gevolg hiervan moet je een pure expressie kunnen vervangen door de waarde ervan zonder dat het gedrag van het programma erdoor gewijzigd wordt.

Gegeven de volgende functie:

function add(a, b) {
  return a + b
}

en de volgende expressie:

add(add(1, 2), add(4, 3)) // 10

kunnen we het substitutieproces illustreren door de vorige expressie te evalueren. We beginnen met een expressie die de add functie drie keer oproept:

add(add(1, 2), add(4, 3))

Vermits add niet afhankelijk van een extern gegeven buiten haar bereik, kunnen we de eerste twee oproepen vervangen door de inhoud:

add(1 + 2, 4 + 3))

En tenslotte ook de laatste oproep:

(1+2) + (4 + 3)

Hogere-ordefunctie

In de wiskunde en in de informatica is een hogere-ordefunctie (of een functionaal) een functie die aan een van de volgende voorwaarden voldoet:

  1. de functie heeft één of meerdere functies als invoer,
  2. de functie levert een functie als uitvoer.

Functies als eersterangs burgers openen de weg voor een ander belangrijk element van functioneel programmeren: hogere-ordefuncties. Een hogere-ordefunctie is een functie die werkt op andere functies. Met andere woorden, een hogere-orde functie kan andere functies als argument aannemen of een nieuwe functie retourneren. Een klassiek voorbeeld van een hogere-ordefunctie is volgende map functie. Een map functie is een hogere-ordefunctie die een functie toepast op elk element van een lijst.

var numbers = [4, 9, 16, 25];
console.log(numbers.map(Math.sqrt)); // [2, 3, 4, 5]
console.log(numbers.map(function(i) {return i * 20})); // [80, 180, 320, 500]

var persons = [
    {firstname : "Jef", lastname: "Inghelbrecht"},
    {firstname : "Mohamed", lastname: "Amajoud"},
    {firstname : "Liesbeth", lastname: "Baten"}
];
console.log(persons.map(function(person) {
    return [person.firstname, person.lastname].join(" ");})); // ["Jef Inghelbrecht", "Mohamed Amajoud", "Liesbeth Baten"]

Pure functies hebben geen neveneffecten. Mogelijke neveneffecten zijn:

Gecontroleerde mutatie

We moeten ons bewijst zijn van het verschillen tussen een mutator method methoden en een accessor method in array's en objecten:

Mutator methoden veranderen de onderliggende objecten.

Je kan dat aan het werk zien als je de volgende code in de console uitprobeert:

var sort = function(array) {
 return array.sort();
}

var slice = function(array) {
 return array.slice(0,2);
}

var fruit = ['peer', 'appel', 'druif', 'kiwi'];

console.log('geordende array: ', fruit);
console.log('geordende array: ', sort(fruit));
console.log('oorspronkelijke array na sort: ', fruit);
console.log('in plakken gesneden array: ', slice(fruit));
console.log('oorspronkelijke array na het in plakken snijden: ', fruit);

Dit is het resultaat:

geordende array:  peer,appel,druif,kiwi
geordende array:  appel,druif,kiwi,peer
oorspronkelijke array na sort:  appel,druif,kiwi,peer
in plakken gesneden array:  appel,druif
oorspronkelijke array na het in plakken snijden:  appel,druif,kiwi,peer

Een pure functie verandert de oorspronkelijke invoer waarde niet:

var items = ['a','b','c'];
var result = pure(items);
// we verwachten dat items nog steeds gelijk is aan ['a','b','c'] en 
// dat het resultaat van de functie enkel te zien is in result

JI
2017-03-05 11:00:30