Het paar DO-LOOP werkt run-time als een BEGIN-AGAIN met de volgende extra's:
- DO ( grens teller -- ) bouwt een tel-mechanisme.
- Binnen de lus is de teller opvraagbaar met I.
- LOOP past na iedere doorloop de teller aan.
- LOOP beëindigt de lus als de teller het opgegeven gebied afgewerkt heeft.
Voor de preciezen onder u: het opgegeven gebied is afgewerkt als de teller het "tussenschot"
tussen 'grens-minus-1' en 'grens' passeert.
Deze redenering geldt ook voor positieve en negatieve stapjes bij
+LOOP.
10 1 DO ... ( 1 2 .. 9 klaar )
0 0 DO ... ( 0 1 .. -2 -1 klaar )
20 0 DO ... 2 +LOOP ( 0 2 .. 18 klaar )
-10 0 DO ... -1 +LOOP ( 0 -1 .. -10 klaar )
0 0 DO ... -1 +LOOP ( 0 klaar )
Je gebruikt
LEAVE om een DO-LOOP voortijdig af te breken:
.. DO .. IF LEAVE THEN .. LOOP aaa
LEAVE ruimt de tel-administratie op en veroorzaakt een sprong naar
aaa, onmiddellijk achter
LOOP.
Ook compile-time lijkt DO-LOOP op BEGIN-AGAIN.
Je kunt daarom met
WHILE een sprong uit een DO-LOOP compileren.
Dat kan gunstig zijn als de voorwaardelijk afgebroken lus heel anders voortgezet
moet worden dan de compleet afgewerkte lus:
.. DO .. WHILE LOOP aaa ELSE .. I .. UNLOOP THEN ..
aaa wordt uitgevoerd als
LOOP de lus beëindigt heeft.
Het stuk tussen
ELSE en
THEN komt uitsluitend na
een voorwaardelijke onderbreking.
Meestal is dit niet op een elegante wijze met
LEAVE te schrijven.
Er vallen twee dingen op:
- Er is altijd expliciet een UNLOOP nodig om run-time
de tel-administratie op te ruimen.
- I is bruikbaar buiten de lus zolang de tel-administratie nog intact is.
LEAVE (altijd) en
LOOP (na de laatste doorloop) voeren impliciet
een
UNLOOP uit.
Tenslotte de CASE-constructie in Forth, een veelbesproken onderwerp.
Is het die aandacht waard?
Ik denk dat
CASE volstrekt overbodig is.
Forth heeft hier voldoende betere formuleringen voor.
Zou het kunnen zijn dat de behoefte aan
CASE vooral gevoeld wordt door
aan Forth beginnende anderstaligen met de begrijpelijke neiging om een-op-een
te vertalen vanuit hun vertrouwde omgeving (DE Forth-drempel m.i.)?