Expressies, variabelen en lussen

Deze site is grotendeels een vertaling van een tutorial van Allison Parrish en is vertaald en bewerkt door Marijn van der Meer voor het gebruik bij Informatica lessen op het IJburg College

Je kan nu iets op het scherm krijgen met p5.js en nog iets met vorm en kleur te doen. Nu is het tijd voor een aantal heel belangrijke concepten in het programmeren: expressies, variabelen en lussen.

Expressies

In de sketches in het vorige hoofdstuk, heb je geleerd functies (zoals ellipse) te gebruiken met parameters. De parameters waren vaste getallen, zoals 100 of 300 bijvoorbeeld. Getallen als 300 of 150 heten in Javascript een waarde. (Later zal je ook nog leren dat waarden niet alleen getallen hoeven te zijn, maar laten we nu alleen even met getallen werken). In alle sketches uit het vorige hoofdstuk werd met in iedere functie een op zichzelf staand getal gebruikt voor de parameters.

Deze individuele op zichzelf staande getallen zijn prima, maar ze zijn maar het begin van het programmeerverhaal. Je kan ieder individueel getal met behulp van expressies combineren met andere getallen. Dit klinkt moeilijker dan het is. Je doet het al met wiskunde. Een expressie is een manier om een nieuw getal te maken door waarden te combineren met operatoren!

Hier gaan we zo verder op in. Eerst eens naar een voorbeeld kijken. Hier staat een simpele sketch die vier cirkels tekent:

Afgezien van de noLoop(), moet na het vorige hoofdstuk deze code nu kunnen begrijpen (op de noLoop() gaan we later nog in). Alle getallen uit de code kunnen vervangen worden door expressies. Een expressie bestaat uit een operator met twee waardes, een waarde links en rechts van de operator. Eigenlijk dus gewoon een som die je uit de wiskunde kent. Hier is bijvoorbeeld dezelfde sketch, maar nu met de opteloperator (+) om de y-positie van alle ellipsen met 50 pixels te veranderen:

Waar er 100 + 50 staat is een voorbeeld van een expressie: twee waardes in combinatie met een operator. De operator in dit geval was de +, maar alle bekende wiskundige operatoren uit je eerdere schooljaren kunnen gebruikt worden, alleen worden een aantal misschien iets anders geschreven dan als je gewend bent:

naam operator
optellen +
aftrekken -
vermenigvuldigen *
delen /
machtsverheffen **

Hier is nog een sketch voorbeeld dat een beetje speelt met deze operatoren:

De operator voor vermenigvuldiging wordt geschreven met een * en die voor delen met een / (Wiskundig zou je het zo kunnen zien: de teller van de breuk staat dus links van de gekantelde breukstreep / en de noemer rechts).

Als je net begint met programmeren kan het voorbeeld van hierboven er raar en ingewikkeld uit zien. Neem bijvoorbeeld deze regel:

ellipse(100, 300 + 50, 150 / 3, 150);

Zo moet je hem hardop lezen:

  • Hier wordt de ellipse functie aangeroepen.
  • In functies worden parameters gescheiden door komma's. Er zijn drie komma's tussen de haakjes dus zijn er vier parameters (Komma's staan alleen tussen de parameters, dus er is een komma minder dan er parameters zijn).
  • De parameters van de functie zijn dan 100, 300 + 50, 150 / 3en 150.
  • 100 en 150 zijn gewoon vaste getallen, maar 300 + 50 en 150 / 3 zijn expressies. Javascript zal deze expressies in een vast getal omzetten als de sketch aangezet wordt (het resultaat is dus 350 voor de een en 50 voor de ander).
  • De volgorde van de parameters is van belang zoals we in het vorige hoofdstuk al zagen, als je niet meer weet wat welk getal bepaalt kijk dan weer even naar de referentiepagina van de ellipse functie. Zoals je ziet of misschien nog weet geeft de eerste parameter de X-positie, de tweede de Y-positie, de derde de breedte en de vierde parameter de hoogte van de ellipse.
  • Dus deze regel zorgt ervoor dat er een ellipse wordt getekend op de X-positie 100, de Y-positie 350 met een diameter in de breedte van 50 en in de hoogte van 150 (Precies wat je ziet in de sketch!).

Als de computer een expressie omzet in een getal heet dat evaluatie. Als je een expressie in je programma zet dan evalueert Javascript deze om het in een waarde om te zetten.

De spaties voor en na de operator zijn overigens niet nodig voor de computer maar maakt de code voor een mens wat leesbaarder soms.

300 + 50

… betekent precies hetzelfde als:

300+50

Iedere programmeur kiest zijn/haar eigen stijl dus kies wat je zelf fijner vindt maar hou je code netjes door een stijl te gebruiken in een programma.

p5.js als een rekenmachine gebruiken

De bovenstaande rekensommen zoals 300 + 50 zijn niet zo moeilijk, waarom zou je dan niet gewoon 350 in je code schrijven? Want je weet allang wat 300 + 50 is? Dat klopt, de voorbeelden van hierboven zijn niet echt nuttig. Maar in het programmeren worden operatoren wel veel gebruikt, zoals je later zult merken. Voornamelijk in combinatie met variabelen zijn ze handig, iets waar we zo op in gaan. Eerst wil ik laten zien dat je p5.js ook als rekenmachine kan gebruiken. Laten we een iets moeilijkere som nemen:

427 * 54

Je kan p5.js gebruiken om deze som uit te rekenen! Begin een nieuwe sketch maar nu in de web editor en kopieer en plak de onderstaande code eens tussen de { en de } na de function setup():

console.log(427 * 54);

Je kan iedere expressie tussen de haakjes typen die je wil en als je dan op de RUN knop klikt, blijft het sketch venster leeg, maar het antwoord van je som staat in het consolevenster of "Debug" venster onder het code venster. (Je kan het ook vinden in het Javascript console van je browser, maar dat is voor gevorderden!)

De console.log() functie is een speciale functie dat niets op het scherm tekent: het enige doel van deze functie is het weergeven van het resultaat van evaluaties van expressies. Je zal later merken dat dit heel handig kan zijn voor het zoeken naar en analyseren van fouten in je programma, vandaar dat ik de console.log() al even noem.

Ingewikkeldere expressies en de volgorde van bewerkingen

Dit zal je waarschijnlijk al bij wiskunde gehad hebben, maar een operator kan een waarde aan beide kanten hebben, maar ook een andere expressie. Je kan er zoveel aan elkaar plakken als je zelf wilt.

Om een expressie deel uit te laten maken van een andere expressie zet je deze tussen haakjes Bijvoorbeeld:

console.log(4 + (5 * 6));

De expressie in deze code is 4 + (5 * 6), waar dus eigenlijk staat: “Tel iets bij elkaar op. Tel de waarde vier bij het antwoord op 5 maal 6 (het antwoord is 34).

Of ingewikkelder:

console.log((18 / 3) - (3 + 2));

Hier halen we het antwoord van 3 + 2 af van het antwoord van 18 / 3. Javascript rekent dit precies hetzelfde uit als je zelf waarschijnlijk doet. Van links naar rechts gaat het de expressies af en evalueert deze (rekent ze uit), zoiets:

  • (18 / 3) - (3 + 2)
  • 6 - (3 + 2)
  • 6 - 5
  • 1

Oefening: Wat is het antwoord van de expressie ((1 + 2) * (3 + 4)) / (9 - 2)? Probeer het eerst uit je hoofd en check daarna je antwoord met de console.log().

Als je de haakjes weg laat gebruikt Javascript dezelfde regels die je bij wiskunde hebt geleerd: Hoe Moeten Wij Van De Onvoldoendes Afkomen? (Haakjes, Machtsverheffen, Worteltrekken, Vermenigvuldigen, Delen, Optellen, Aftellen). Dus in de volgende expressie:

4 + 5 * 6

evalueert Javascript eerst het vermenigvuldigen (5 * 6) en daarna het optellen (4 + 30), en dat geeft als antwoord 34. Om Javascript eerst het optellen te laten evalueren moeten we die expessie tussen haakjes zetten:

(4 + 5) * 6

… en dat geeft 54 als antwoord (negen keer zes).

Zelf zet ik meestal haakjes om expressies die ik eerst wil laten evalueren, zonder aan de volgorde te denken. Dit omdat ik dan minder (onverwachte) fouten maak in mijn code en ik vind het makkelijker leesbaar.

Variabelen

Nu dat je waarden en expressies begrijpt is het tijd voor een van de meest krachtige concepten in programmeren: variabelen.

Waarden veranderen met zoek en vervang

Om variabelen uit te leggen gaan we terug naar de code van de vier cirkels van iets eerder:

Ziet er best aardig uit, maar de cirkels zijn wat groot! Ik wil ze wat kleiner, zeg 100 pixels in diameter in plaats van 150. Er staat wel heel vaak 150 om te veranderen. Maar ik ben slim in een teksteditor kan ik zoek en vervang gebruiken. Zoek alle 150 en vervang voor 100. Het resultaat staat hieronder:

Maar nu vind ik ze toch weer wat klein. Wat ik nu toch heel wat anders wil en ik wil ze juist veel groter. Misschien wel 200 pixels diameter? Nog een keer een zoek en vervang, nu van 100 naar 200. Wat krijgen we nu…

Oh oh. Dit was niet de bedoeling. Wat gebeurde er?

Ik zie nu dat de 100 niet alleen de nieuwe waarde was van de diameter van de cirkel, maar ook de waarde van een aantal X en Y coordinaten van de cirkels. Dus nu zijn met zoek en vervang deze waarden per ongeluk ook veranderd. Vervelend, irritant, ik vind de cirkels stom en ik haat vervolgens het vak informatica...

Leve de variabelen!

Hoe zou je dit probleem kunnen oplossen? Je wilt eigenlijk dezelfde waarde op meerdere plekken gebruiken en als je die waarde wilt veranderen wil je dat maar een keer moeten doen in plaats van op meerdere plekken in je code. Zou het niet geweldig zijn als er een soort ladenkast zou zijn waar je in een laatje een waarde in zou kunnen stoppen en op de la zou kunnen schrijven wat er in zit? En als je die waarde nodig hebt dat je dan alleen de naam van de la hoeft te gebruiken en in die la ook makkelijk een andere waarde zou kunnen stoppen? Dus in dit geval zou je een laatje willen hebben met de naam diameter en daar de waarde 200 in stoppen...

Er bestaat zo'n laatje in iedere programmeertaal, dus ook in Javascript en deze heet: een variabele.

Ok, het is niet echt een laatje uiteraard. Er is is wel een virtuele ladenkast in de vorm van een regel in je code waarin je een waarde een naam geeft en die naam overal in je code kan gebruiken als je die waarde nodig hebt, in plaats van het typen van die waarde. Zo ziet dat eruit:

De regel helemaal bovenaan de sketch, zelfs boven de function setup() { is een variabele declaratie, het vaststellen van een variabele. Het declareren van een variabele heeft het volgende format:

  • Het woord var, gevolgd door
  • de naam van de variabele (zeg, maar de naam van het laatje, die mag je zelf bepalen!), gevolgd door
  • een "is" teken (=), gevolgd door
  • een expressie die de waarde "geeft" die jij wilt aan de variabele (die je in je laatje stopt).

Dus in deze sketch is de variabele met de naam diameter vastgesteld met de waarde 200. En overal in de sketch waar ik deze waarde wil gebruiken kan je het woord diameter gebruiken in plaats van de waarde zelf. Als ik nu de diameter van de cirkels wil veranderen, dus de waarde aanpassen, dan hoef ik dat op nog maar een plek te doen:

Je kan zo veel variabelen in je code toevoegen als je zelf wilt. Dus als ik de hoogte en breedte van de cirkels nog niet zeker weet en ze misschien zou willen veranderen dan zou ik twee variabelen kunnen toevoegen, een voor de hoogte en een voor de breedte:

Laten we daar eens even mee spelen:

Zie dat er niets bijzonders is aan de namen van de variabelen die je kiest diameter, cirkelBreedte en cirkelHoogte. Je mag zelf de namen verzinnen, maar het is wel aan te raden en gebruikelijk om namen te kiezen die duidelijk maken wat de variabelen doet, waar deze voor gebruikt wordt. Zo weet je later nog wat je deed en kunnen anderen ook je code beter begrijpen. Maar je mag ook dit doen:

Zo lang je maar exact dezelfde spelling aanhoudt (inclusief hoofdletters en kleine letters), zullen je variabelennamen doen wat ze moeten doen, hoe je ze ook noemt.

Namen van variabelen

Er zijn toch wel een paar regels bij het geven van namen. De regels van Javascript zijn:

Ook zijn er verschillende gereserveerde keywords in Javascript, die je niet als variabele kan gebruiken, omdat ze al voor iets anders worden gebruikt. Hier zie je de lange lijst..

En het is uiteraard ook niet verstandig om een naam te gebruiken van een van de ingebouwde p5.js variabelen of functienamen. Je code kan heel raar gaan doen als je een variabele ellipse noemt. Raadpleeg de p5.js referentie voor de hele lijst. Maar over het algemeen hoef je je geen zorgen te maken en kom je vaak zelf wel op andere namen. Maar mocht je code iets onverwachts raars doen kan je dus controleren of het aan een gekozen variabelenaam ligt.

Foutmeldingen met variabelen

De foutmelding die het meeste voor komt en die je zeker een keer tegenkomt is het moment dat je de gekozen variabelenaam verderop in je code verkeerd spelt of vergeten bent aan te maken. Als dit gebeurt zal Javascript je een “Uncaught ReferenceError” foutmelding geven, dat betekent dat je een variabele hebt aangeroepen die Javascript niet herkent (hij kan het laatje niet vinden). Er staat vrijwel altijd ook een getal bij de foutmelding dat aangeeft in welke regel Javascript denkt dat de fout zit. Dit is heel fijn.

Variabelen en expressies

Ok, variabelen. Je snapt ze en kan ze gebruiken. Het zijn waarden waar je een naam aangeeft en je kan die naam gebruiken in je code in plaats van de originele waarde. Nu kan je de waarde makkelijk veranderen zonder je hele code weer te moeten doorlopen. Handig en fijn.

Maar de kracht van variabelen is dat je ze kan gebruiken op precies zo'n manier als een waarde (getal) Dit betekent dat je variabelen bijvoorbeeld ook in expressies kan gebruiken. Hier zijn bijvoorbeeld weer onze vier cirkels, maar nu gebruiken we de diameter variabele in combinatie met een expressie om de grootte van de cirkels een klein beetje te veranderen, voor iedere cirkel weer:

De "basis" diameter van iedere cirkel wordt bepaald door de variabele, maar nu kunnen we de waarde van de variabele heel makkelijk een beetje veranderen voor een kleine variatie:

Je kan ook variabelen gebruiken die je daarvoor al gedeclareerd (gemaakt) hebt. Stel je voor dat we van iedere cirkel de hoogte precies twee keer zo groot willen als de breedte. Dat kan je zo doen:

Je kan nu de waarde van ellipseBreedte aanpassen en de verhouding van de ellips blijft hetzelfde zonder dat je hoeft te stoeien met de waarde van ellipseHoogte:

Hier is een sketch dat alles samenvoegd: het tekent een rij van vijf rechthoeken door het gebruik van variabelen en expressies om kleine variaties aan te brengen in iedere rechthoek. Je kan de variabelen aanpassen zonder de eigenlijke code aan te passen (en eventueel per ongeluk te verpesten) die in de draw() functie staat.

Probeer maar eens wat waarden in de variabelen te veranderen om te zien wat er gebeurt (en wat gebeurt er als je negatieve waarde invoert bij een variabele, zoals bijvoorbeeld -25 for xstep?) Als je niet precies begrijpt wat er in de code gebeurt probeer dan regel voor regel door iedere functie te gaan en de expressie te evalueren (Wat komt er bijvoorbeeld uit de expressie (xpos+(xstep*4))?

Opmerking: noStroke() werkt precies als stroke() of strokeWeight(), alleen vertelt het p5.js om de omlijning weg te laten (dus niet te tekenen). De noFill() functie doet hetzelfde met de vulkleur van een vorm. Probeer het maar uit!

Herhaling met variatie

Als je ondertussen al een beetje bent gaan denken als een programmeur en jezelf al een beetje een nerd gaat voelen, had je misschien al het idee bij het vorige voorbeeld. "Dit is wel heel veel herhaling" Als ik dit had moeten overtypen had ik wel heel veel vrijwel hetzelfde moeten typen. En veel typen doen alleen sukkels. Hadden we vorige periode niet iets geleerd over herhaling en was het niet juist een computer die dat goed kan en niet een mens?

Laten we eerst een wat simpeler voorbeeld nemen. Deze sketch tekent vijf cirkels op een rij:

Dus we hebben hier vijf precies dezelfde cirkels met het enige verschil dat de X-positie verandert. Dit is te doen, maar wat als ik iets wil veranderen. Bijvoorbeeld:

  • Wat als ik het aantal cirkels wil veranderen? Een extra cirkel toevoegen valt wel mee, maar wat als ik er honderd of misschien wel een miljoen wil tekenen? (Dat klinkt nu wat veel maar je zal later merken dat een miljoen dingen op het scherm tekenen misschien vaker gebeurt dan je denkt).
  • En wat als ik de diameter per cirkel zou willen veranderen? Ik zou variabelen kunnen gebruiken, maar moet ik er echt zoveel maken als er cirkels zijn?
  • En wat als ik andere attributen van de cirkel in een herhaling zou willen laten veranderen, zoals met de kleur van rechthoeken van het vorige voorbeeld?

Allemaal goede vragen. We willen een gereedschap hebben waarin we p5.js kunnen vertellen dat we niet een individuele vorm willen, maar een hele serie van vormen die bepaalde attributen delen. Met andere woorden we willen herhalen met variatie.

Je ziet dat de regels met de ellipse() code eigenlijk de hele tijd hetzelfde doen en dezelfde waarden gebruiken. Om het nog wat duidelijker te maken herschrijven we het voorbeeld nog een beetje, zodat iedere aanroep van de ellipse() een vermenigvuldiging heeft en niet alleen de laatste drie:

Deze code maakt het nog duidelijker dat iedere aanroep van de ellipse() functie eigenlijk exact hetzelfde is, behalve het getal aan de rechterkant van de vermenigvuldiging. Dit kan natuurlijk makkelijker.

De for lus

En die is er uiteraard! Anders was ik er niet over begonnen (en zoals je je misschien kan herinneren van de vorige periode). Dit principe van herhalen heet in programmeertaal een loop (in het Nederlands een lus, maar ik zal het vanaf nu de Engelse benaming, loop, aanhouden). Het heet een lus of loop omdat het de computer na een lijst van instructies de weer opnieuw dezelfde instructies laat uitvoeren en waarschijnlijk nog wel een paar keer. Er zijn verschillende manieren waarop je een loop kan maken in Javascript. Degene die we als eerste gaan leren is de for loop. De for loop heeft een heel flexibele structuur die daardoor op meerdere manieren is te gebruiken, maar we beginnen met een vorm en die ziet er zo uit:

for (var i = 0; i < keer; i++) {
    ... en schrijf hetgeen je wil laten herhalen hier ...
}

Vervang het woord keer in het code stukje hierboven met het aantal keer dat je wilt dat de loop wordt herhaald

Tussen de accolades ({ en }), moet je de statements schrijven die je wilt herhalen. Als je normaal een getal geleidelijk toe zou laten willen nemen, schrijf dan de variabele i daarvoor in de plaats. (De variabele i is alleen aanwezig in de for loop.)

Dit klinkt heel abstract en ingewikkeld, dus hier is een voorbeeld dat hopelijk veel verklaart:

En met deze korte code van twee regels hebben we de vijf regels uit het eerdere voorbeeld vervangen. Niet slecht! Hier is nog een versie van de code die nu negen cirkels tekent in plaats van vijf (de waarden voor de xstep en de diameter van de cirkels zijn wat aangepast om het te laten passen):

Probeer eens te spelen met dit voorbeeld door de code te veranderen en probeer te bedenken wat je nog meer kan doen. De sketch hieronder brengt wat variatie in de grootte van de cirkels en heeft een fill() toegevoegd die ook gebruik maakt van de i variabele om de kleur van iedere vorm geleidelijk te veranderen en herhaalt zich wel 12 keer in plaats van 9:

Je kan zo veel statements (regels) in een for loop stoppen als je wilt (en met "in een for loop stoppen" bedoel ik "tussen de accolades.") Elk statement zal keer op keer opnieuw weer worden uitgevoerd.

OEFENING: Neem een van de voorbeelden die een for loop gebruikt en schrijf het eens uit. Welke statements (regels) had je moeten schrijven als je geen for loop had gebruikt?

Nog dieper de for loop in

In de basis is de for loop gewoon een manier van tellen. Het makkelijkst om dit te laten zien is met de console.log(). Kopieer en plak de volgende code tussen de { en } na de setup() functie in een nieuwe sketch in de editor en klik op RUN:

for (var i = 0; i < 10; i++) {
    console.log(i);
}

De console output zal er zo uit zien:

0
1
2
3
4
5
6
7
8
9

Zoals je kan zien print deze code heel simpel de getallen van nul tot negen (dat zijn tien herhalingen, startend met nul).

De for loop kan ook gebruikt worden voor een iets geavanceerdere manier van tellen, gebruik het volgende code stukje:

for (var i = start; i < eind; i += stap) {
  ... your statements here ...
}

In het bovenstaande code stukje moet je de volgende veranderening aanbrengen:

  • start: Vervang dit woord voor het getal waar je wil beginnen met tellen.
  • eind: Vervang dit woord met het getal waar je loop moet stoppen.
  • stap: Vervang dit woord met hoeveel je getal moet toenemen met iedere stap.

Hier bijvoorbeeld, telt de loop van 100 (maar niet inclusief honderd) tot 300 in stappen van 40:

for (var i = 100; i < 300; i += 40) {
  console.log(i);
}

En deze laat alle even nummers zien vanaf 10 tot (en niet met) 50:

for (var i = 10; i < 50; i += 2) {
  console.log(i);
}

Je kan de for loop op deze manier dus gebruiken om de stappen in de herhaling precies te bepalen zoals jij wilt. Bijvoorbeeld:

Geneste loops

Wat als we een raster van cirkels willen, in plaats van maar een lijn van cirkels? We zouden het zo kunnen doen, door te kopieren en te plakken:

Maar wacht. Doen we nu nou weer precies hetzelfde. Het herhalen van code met maar een kleine variatie net zoals iets eerder in dit hoofdstuk? En dan optellen van nul tot een ander getal? En was dit precies het probleem waar de for loop voor was bedacht om dit op te lossen? En inderdaad. Je kan een for loop in een andere for loop. Wanneer je een tweede for loop gebruikt, moet je wel een andere variabele naam gebruiken dan i in de tweede loop. Het is gebruikelijk om voor de tweede loop dan de j te nemen. Zo ziet de code er nu uit:

LET OP: Het aantal cirkels dat wordt getekend is precies 45, dus 5 keer 9. Leg in je eigen woorden uit waarom dat zo is.

OEFENING: Neem het voorbeeld hierboven over en probeer met de variabelen i en j wat variatie in te brengen. Verander bijvoorbeeld de vulkleur, de dikte van de lijn, de grootte van de cirkels enz.!

Comments

Broncode kan rommelig en onduidelijk worden. Zeker als je de volgende dag weer verder gaat of iemand anders je code gaat lezen weet je soms niet meer (direct) wat er gebeurt. Dan helpt het als je bij je code kan schrijven wat het doet of wat je dacht toen je dat stukje code schreef. Je kan er niet zo maar eigen woorden tussen schrijven, want dan snapt de computer je code niet meer. Dus hier is ook een bepaalde syntax voor: de karakters //. Als er ergens // staat op een regel zal de computer de tekst na deze karakters op die regel niet uitvoeren tot het einde van de regel. Hier is een sketch die het gebruik van commentaar, comments in het Engels, demonstreert:

Comments worden ook vaak gebruikt om regels code in je programma "tijdelijk" uit te schakelen. Als je de sketch hierboven uit laat voeren en graag even wilt zien hoe deze eruit ziet zonder de middelste cirkel, zonder de hele regel weg te gooien, kan je heel simpel even // aan het begin van de regel zetten. (Dit heet onder programmeurs “commenting it out”).

Comments zijn ook heel fijn als je met anderen samenwerkt aan een programmeerproject. Je kan andere wijzen op lastige stukken code of onduidelijkheden verduidelijken of nog even aangeven wat er nog moet gebeuren.

Je kan hier meer lezen over het gebruik van comments in Javascript, inclusief de syntax voor het maken van comments die meerdere regels bevatten.