3.18 General Loops

The endless loop is the most simple one:

: endless ( -- )
  0 begin
    dup . 1+
  again ;
endless

Terminate this loop by pressing Ctrl-C (in Gforth). begin does nothing at run-time, again jumps back to begin.

A loop with one exit at any place looks like this:

: log2 ( +n1 -- n2 )
\ logarithmus dualis of n1>0, rounded down to the next integer
  assert( dup 0> )
  2/ 0 begin
    over 0> while
      1+ swap 2/ swap
  repeat
  nip ;
7 log2 .
8 log2 .

At run-time while consumes a flag; if it is 0, execution continues behind the repeat; if the flag is non-zero, execution continues behind the while. Repeat jumps back to begin, just like again.

In Forth there are a number of combinations/abbreviations, like 1+. However, 2/ is not one of them; it shifts its argument right by one bit (arithmetic shift right), and viewed as division that always rounds towards negative infinity (floored division), like Gforth’s / (since Gforth 0.7), but unlike / in many other Forth systems.

-5 2 / . \ -2 or -3
-5 2/ .  \ -3

assert( is no standard word, but you can get it on systems other than Gforth by including compat/assert.fs. You can see what it does by trying

0 log2 .

Here’s a loop with an exit at the end:

: log2 ( +n1 -- n2 )
\ logarithmus dualis of n1>0, rounded down to the next integer
  assert( dup 0 > )
  -1 begin
    1+ swap 2/ swap
    over 0 <=
  until
  nip ;

Until consumes a flag; if it is zero, execution continues at the begin, otherwise after the until.

Assignment: Write a definition for computing the greatest common divisor.

Reference: Simple Loops.