Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

range and rangeby

Final provides two useful words for setting up counted iterated loops. range is for a definite counted loop with an increment of 1. rangeby is more flexible. They are described below. For detailed descriptions and stack effects, use help.

range

range takes an inclusive Int start and end value, and can then provide an Iterator for foreach. i is the value of the iteration value for that step, and starts with beg and ends with end. When using range to iterate over a counted zero-based range, you set beg to 0 and the end to be count-1. If the count is 0, no iterations are performed. The resulting i will be an Int.

> // ( -- )
: count1to5
  1 5 range
  foreach
    i $ sp
  /foreach
  nl
;
count1to5

1 2 3 4 5

Zero-based index style (here: three slots, indices 0 1 2):

> // ( count:i -- )
: indices
  0 swap 1 - range
  foreach
    i $ sp
  /foreach
  nl
;
3 indices

0 1 2

An empty range is legal and runs zero iterations — useful when a computed end would otherwise need a special “nothing to do” case.

rangeby

rangeby takes a beg, end, and step value. Step can be negative if beg>=end. The values can be of any numeric type, but they must all be the same type. This enables fractional Float step values. The iteration stops when the value goes beyond the end value. As with range, an empty range that has no first value is legal, and results in no iterations. i is the same type as the inputs.

> // ( -- )
: byTens
  0 40 10 rangeby
  foreach
    i $ sp
  /foreach
  nl
;
byTens

0 10 20 30 40

Float step:

> // ( -- )
: halves
  0.0 2.0 0.5 rangeby
  foreach
    i $ sp
  /foreach
  nl
;
halves

0 0.5 1 1.5 2

Counting down (negative step; beg >= end):

> // ( -- )
: countdown
  5 1 -1 rangeby
  foreach
    i $ sp
  /foreach
  nl
;
countdown

5 4 3 2 1