-
Notifications
You must be signed in to change notification settings - Fork 0
Functional Programming
In dit vak gaan we aan de slag met functional programming. Maar wat is functional programming nu precies? Dat leg ik hier kort voor mezelf vast.
Met functional programming zorg je ervoor dat zoveel mogelijk, het liefst alle, functies iets returnen. Alle functies zijn als het ware 'getters' die iets teruggeven wanneer deze worden aangeroepen. Er wordt dus meer gefocust op de functies. Je maakt meerdere kleine functies zodat je deze kunt terugroepen. Functies kun je in javascript opslaan in variablen. Als je meerdere keren een specifiek datastuk nodig hebt, is het mogelijk om simpelweg de variable met die functie aan te roepen in plaats van elke keer weer die if/else-statement of for-loop te moeten schrijven.
Bij functional programming zorg je ervoor dat alle variablen binnen zijn eigen scope worden gebruikt, gewijzigd en aangemaakt. Als je data nodig hebt van een andere scope, zoals de global scope, geef je deze mee met een parameter. Op deze manier kun je die data binnenhalen en bewerken. Ook blijft de oorspronkelijke data in tact en worden deze niet overridden.
Er zijn meerdere functional patterns binnen functional programming. Zo'n functional pattern stel je van te voren vast. Een pattern is een set van standaarden en best practices om je code consistent te houden. Door met patterns te werken leer je om beter en mooier code te schrijven. Hier leg ik kort de verschillende patterns uit.
Filter is een methode die zelf, zonder een for-loop of while, door een array heen gaat en deze filtered. De filter maakt dan gebruik van zijn eigen functie, 'callback', om een nieuwe array terug te geven die gefiltered is met de parameter die je hebt meegegeven.
Zonder filter
function filterThisArray(arr){
let filteredArray = []
for (let c = 0; c < arr.length; c++) {
if(arr[c] != "a")
filteredArray.push(arr[i])
}
return filteredArray
}
Met filter
function filterThisArray(arr){
return arr.filter(item => item != "a")
}
Een andere higher-order function is map. Map werkt een beetje het zelfde als forEach(), alleen geeft Map net als filter een array terug. Map gebruik je dus alleen als je echt een array terug wil hebben en die weer wilt gebruiken. Als je alleen maar een query hoeft uit te voeren over een bestaande array, kun je beter forEach() gebruiken.
Zonder map
function forEachArrayItem(arr){
let remappedArray = []
for (let c = 0; c < arr.length; c++){
remappedArray[c].replace('a', 'b')
}
return remappedArray
}
Met map
function forEachArrayItem(arr){
return arr.map(items => items.replace('a', 'b'))
}
Met pure functions zorg je ervoor dat je variablen alleen binnen de scope van de functie aanpast. Je kunt dan geen globale variable, buiten de function scope, aanpassen. Je geeft deze dan eerst mee met een parameter.
De impure versie is de sloderige versie. Hier pas je een variable aan buiten de scope van de functie
let aNumber = 1
function changeNumber() {
return aNumber++
}
changeNumber()
Een netterie, pure, manier is schoner aangezien de oorspronkelijke data onaangetast blijft.
let aNumber = 1
function changeNumber(number) {
return number++
}
changeNumber(aNumber)
Immutability lijkt heel erg op pure functions. Alleen bij immutability gaat het om de data en niet om de functions. Bij immutability zorg je ervoor dat je de data, als in variablen en array's, niet direct aanpast. Deze laad je in via een parameter en vervolgens geef je een nieuwe variable, aangepast in de functie, weer terug.
Bij composition hak je de functies in kleine functions die 1 simpel dingetje doen. Deze functies kun je dan chainen om je antwoord te krijgen. Door je functies in kleine delen op te splitsen, is veel van je code herbruikbaar.
function getAnswerOfQuery(list, query){
let results = list.map(answer => answer[query]) // Create new array of the specific column called results
let removedEmptyItems = removeEmptyItems(results) // Check if there are empty items in the array
let hashResultsChecked = checkHash(removedEmptyItems) // Check if string begins with #
let dataCleaned = checkHexCode(hashResultsChecked) // Check if string is a HEX
return dataCleaned // Return the cleaned data
}
Door een standaard te zetten voor de naamgeving van de functies, is je code leesbaarder wanneer je gebruik gemaakt van de andere functional patterns. Zo kun je de standaard zetten zoals: Voor elke functie waar ik data op haal, begin ik mijn functie met het woord 'get'. Op die manier weet je wanneer je een functie aanroept die begint met 'get', dat deze data ophaald uit of van iets.
Voor goede, leesbare en bruikbare code is het het beste om je vaste variables van de global scope zo veel mogelijk bovenaan te definiëren. In de meeste gevallen, aangezien dit vaste variables zijn, geef je ook de declaratie const mee aan deze variablen
In mijn code maak ik gebruik van verschillende functional patterns. Hieronder geef ik per functional pattern één of meerdere voorbeelden vanuit mijn code.
- Voorbeeld Pure functions & Immutability 1
- Voorbeeld Pure functions & Immutability 2
- Voorbeeld Pure functions & Immutability 3
- Guru99
- Wikipedia
- Fun Fun Functions
- CMDa-tt course-20-21
- Robert Spier tijdens stand-up